<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="Wang_boWen js知识点总结(持续更新), W.BOWEN&#39;s blog">
    <meta name="description" content="接受失败,但不选择放弃">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>Wang_boWen js知识点总结(持续更新) | W.BOWEN&#39;s blog</title>
    <link rel="icon" type="image/png" href="/wangbowen-hexo-blog/favicon.png">

    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/css/my.css">

    <script src="/wangbowen-hexo-blog/libs/jquery/jquery.min.js"></script>

<meta name="generator" content="Hexo 5.3.0"></head>




<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/wangbowen-hexo-blog/" class="waves-effect waves-light">
                    
                    <img src="/wangbowen-hexo-blog/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">W.BOWEN&#39;s blog</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/wangbowen-hexo-blog/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/wangbowen-hexo-blog/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/wangbowen-hexo-blog/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/wangbowen-hexo-blog/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/wangbowen-hexo-blog/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/wangbowen-hexo-blog/contact" class="waves-effect waves-light">
      
      <i class="fas fa-comments" style="zoom: 0.6;"></i>
      
      <span>留言板</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/wangbowen-hexo-blog/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>友情链接</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/wangbowen-hexo-blog/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">W.BOWEN&#39;s blog</div>
        <div class="logo-desc">
            
            接受失败,但不选择放弃
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/wangbowen-hexo-blog/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/wangbowen-hexo-blog/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/wangbowen-hexo-blog/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/wangbowen-hexo-blog/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/wangbowen-hexo-blog/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/wangbowen-hexo-blog/contact" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-comments"></i>
			
			留言板
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/wangbowen-hexo-blog/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友情链接
		</a>
          
        </li>
        
        
        <li><div class="divider"></div></li>
        <li>
            <a href="https://gitee.com/wang-bowen" class="waves-effect waves-light" target="_blank">
                <i class="fab fa-github-square fa-fw"></i>Fork Me
            </a>
        </li>
        
    </ul>
</div>


        </div>

        
            <style>
    .nav-transparent .github-corner {
        display: none !important;
    }

    .github-corner {
        position: absolute;
        z-index: 10;
        top: 0;
        right: 0;
        border: 0;
        transform: scale(1.1);
    }

    .github-corner svg {
        color: #0f9d58;
        fill: #fff;
        height: 64px;
        width: 64px;
    }

    .github-corner:hover .octo-arm {
        animation: a 0.56s ease-in-out;
    }

    .github-corner .octo-arm {
        animation: none;
    }

    @keyframes a {
        0%,
        to {
            transform: rotate(0);
        }
        20%,
        60% {
            transform: rotate(-25deg);
        }
        40%,
        80% {
            transform: rotate(10deg);
        }
    }
</style>

<a href="https://gitee.com/wang-bowen" class="github-corner tooltipped hide-on-med-and-down" target="_blank"
   data-tooltip="Fork Me" data-position="left" data-delay="50">
    <svg viewBox="0 0 250 250" aria-hidden="true">
        <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
        <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
              fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
        <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
              fill="currentColor" class="octo-body"></path>
    </svg>
</a>
        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/wangbowen-hexo-blog/medias/featureimages/1.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">Wang_boWen js知识点总结(持续更新)</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/wangbowen-hexo-blog/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/wangbowen-hexo-blog/tags/JavaScript/">
                                <span class="chip bg-color">JavaScript</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2021-11-03
                </div>
                

                

                

                

                
            </div>
        </div>
        <hr class="clearfix">

        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <h2 id="V8引擎执行流程"><a href="#V8引擎执行流程" class="headerlink" title="V8引擎执行流程"></a>V8引擎执行流程</h2><ol>
<li>Blink将JavaScript源码交给V8引擎,Stream获取到源码并且进行编码转换;</li>
<li>Scanner会进行此法分析，词法分析会将代码转换成tokens;</li>
<li>接下来tokens会被转换成AST树,经过parser和Preparser:</li>
</ol>
<ul>
<li>parser就是直接将tokens转换成AST树结构;</li>
<li>Preparser称之为预解析,为什么需要预解析?<ul>
<li>因为并不是所有JavaScript代码,在一开始时就会被执行。对所有JavaScript代码进行解析,会影响<br>网页运行效率;</li>
<li>所以V8引擎实现了Lazy Parsing(<code>延迟解析</code>)的方案,它的作用是将不必要的函数进行<code>预解析</code>,也就是<br>解析暂时需要的内容,而对<code>函数的全量解析</code>是在<code>函数被调用时</code>才会进行;</li>
</ul>
</li>
</ul>
<ol start="4">
<li>生成AST树后,会被Ignition转成字节码,之后的过程就是代码的执行过程。</li>
</ol>
<h2 id="作用域规范"><a href="#作用域规范" class="headerlink" title="作用域规范"></a>作用域规范</h2><ol>
<li>早期版本ECMA的版本规范:</li>
</ol>
<ul>
<li>每个执行上下文会被关联到一个<code>变量对象(variable object, VO)</code>,在源代码中的变量和函数声明会被作为属性添加到VO中。对于函数来说,参数也会被添加到VO中。</li>
</ul>
<ol start="2">
<li>最新版本ECMA的版本规范:</li>
</ol>
<ul>
<li>每个执行上下文会关联到一个<code>变量环境(variable Environment)</code>中,在执行代码中变量和函数声明会作为<code>环境记录(Environment Record)</code>添加到变量环境中。对于函数来说,参数也会被作为环境记录添加到变量环境中。</li>
</ul>
<ol start="3">
<li>作用域执行顺序(待完善):<!-- - 首先创建一个GO(GlobalObject)全局 -->

</li>
</ol>
<h2 id="内存管理"><a href="#内存管理" class="headerlink" title="内存管理"></a>内存管理</h2><ol>
<li>js对于<code>基本数据类型内存的分配</code>会在执行时,直接在栈空间进行分配;</li>
<li>js对于<code>复杂数据类型内存的分配</code>会在堆内存中开辟一块空间,并且将这块空间的指针返回值变量引用;</li>
</ol>
<h2 id="常见的GC算法"><a href="#常见的GC算法" class="headerlink" title="常见的GC算法"></a>常见的GC算法</h2><ol>
<li>引用计数：</li>
</ol>
<ul>
<li>当一个对象有一个引用指向它时,那么这个对象的引用就+1,当以个对象的引用为0时,这个对象就可以被销毁;</li>
<li>弊端: 会产生循环引用;</li>
</ul>
<ol start="2">
<li>标记清除:</li>
</ol>
<ul>
<li>设置一个根对象(root object),垃圾回收器会定期从这个根开始,找所有从根开始有引用到的对象,对于那些没有引用到的对象,就认为是不可用的对象;</li>
<li>能够很好解决循环引用问题;</li>
</ul>
<h2 id="闭包的定义"><a href="#闭包的定义" class="headerlink" title="闭包的定义"></a>闭包的定义</h2><ol>
<li><p>一个普通的函数function,如果它可以访问其外层作用域的自由变量,那么这个函数就是一个闭包(内层函数可以访问到其外层函数的作用域);</p>
</li>
<li><p>在JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> name = <span class="string">&#x27;wbw&#x27;</span>;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;bar&#x27;</span>, name);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> bar;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> fn = foo();</span><br><span class="line">fn();</span><br></pre></td></tr></table></figure>
<h2 id="执行上下文"><a href="#执行上下文" class="headerlink" title="执行上下文"></a>执行上下文</h2></li>
<li><p>一般包括<code>作用域链(scopeChain)</code>、<code>this</code>、<code>arguments</code>和<code>函数变量对象AO或全局变量对象GO</code>;</p>
</li>
<li><p>this</p>
<ul>
<li>函数在调用时候,JavaScript会默认给this绑定一个值;</li>
<li>this的绑定和定义的位置(编写的位置)没有关系;</li>
<li><code>this的绑定与调用的方式和调用的位置有关系</code>;</li>
<li>this是在运行时被绑定的;</li>
</ul>
</li>
<li><p>this的绑定规则</p>
<ul>
<li>默认绑定: 独立函数调用;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 案例一:</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">this</span>); <span class="comment">// window</span></span><br><span class="line">&#125;</span><br><span class="line">foo();</span><br><span class="line"><span class="comment">// 案例二:</span></span><br><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  foo: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> bar = obj.foo</span><br><span class="line">bar(); <span class="comment">// window, this的绑定与调用的方式及调用的位置有关系</span></span><br></pre></td></tr></table></figure></li>
<li>隐式绑定: 满足<code>xxx.fn()</code>格式,fn的<code>this</code>指向<code>xxx</code>。如果存在链式调用,<code>this永远指向最后调用它的那个对象</code>;</li>
<li>隐式绑定条件: 1. 必须在调用的对象内部有一个对函数的引用;2. 没有这个引用,调用时会报错;3.正是通过这个引用,<code>间接将this绑定到了这个对象上</code>;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  foo: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">obj.foo(); <span class="comment">// this指向的是obj对象</span></span><br></pre></td></tr></table></figure></li>
<li>显示绑定: 通过call或applay在执行函数时,明确绑定this;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line">foo.call(obj, n1, n2...); <span class="comment">// this指向call函数第一个传入的值,在这里指向的是obj</span></span><br><span class="line">foo.applay(obj, [n1, n2...]);</span><br></pre></td></tr></table></figure></li>
<li>显示绑定优先级要高于隐式绑定;</li>
<li>new绑定: 通过new关键字来调用构造函数,生成一个新对象(this指向创建出来的对象实例);</li>
</ul>
</li>
<li><p>this的其他绑定</p>
<ul>
<li>setTimeout、setInterval、forEach、map等函数调用时,this指向的是window。</li>
<li><code>箭头函数</code>的this指向的是它上一层作用域中的this。</li>
<li><code>立即执行函数</code>的this指向的是全局对象window。</li>
<li><code>严格模式</code>下的自指向函数的this指向的是undefined。</li>
</ul>
</li>
<li><p>规则优先级</p>
<ul>
<li><code>默认规则(默认绑定)</code>的优先级最低。</li>
<li><code>显示绑定</code>的优先级是高于<code>隐式绑定</code>的。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  foo: foo.bind(<span class="string">&#x27;abc&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line">obj.foo(); <span class="comment">// this打印为abc</span></span><br></pre></td></tr></table></figure></li>
<li><code>new绑定</code>优先级高于<code>隐式绑定</code><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  foo: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> f = <span class="keyword">new</span> obj.foo(); <span class="comment">// this打印为foo&#123;&#125;</span></span><br></pre></td></tr></table></figure></li>
<li><code>new绑定</code>优先级高于<code>显示绑定</code>(注意: new关键字不能和call/apply一起使用)<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> bar = foo.bind(<span class="string">&#x27;aaa&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> obj = <span class="keyword">new</span> bar(); <span class="comment">// 最后打印的this为foo&#123;&#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>特殊绑定: 忽略显示绑定</p>
<ul>
<li>call/apply/bind: 当传入null/undefined时,自动将this绑定成全局对象;</li>
<li>间接函数引用: this绑定成全局对象;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;window&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> person = &#123;</span><br><span class="line">  name: <span class="string">&#x27;person&#x27;</span>,</span><br><span class="line">  sayName: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">(b = person.sayName)(); <span class="comment">// window,间接函数引用</span></span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>箭头函数 </p>
<ul>
<li>箭头函数不会绑定this、argument属性;</li>
<li>箭头函数不能作为构造函数使用(不能和new一起使用,会报错);</li>
</ul>
</li>
<li><p>this面试题</p>
<ul>
<li>面试题一<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;window&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> person = &#123;</span><br><span class="line">  name: <span class="string">&#x27;person&#x27;</span>,</span><br><span class="line">  sayName: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sayName</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> sss = person.sayName;</span><br><span class="line">  sss(); <span class="comment">// window,独立函数调用</span></span><br><span class="line">  person.sayName(); <span class="comment">// person,隐式调用</span></span><br><span class="line">  (person.sayName)(); <span class="comment">// person: 隐式调用</span></span><br><span class="line">  (b = person.sayName)(); <span class="comment">// window,间接函数引用(独立函数调用)</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li>面试题二<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;window&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> person1 = &#123;</span><br><span class="line">  name: <span class="string">&#x27;person1&#x27;</span>,</span><br><span class="line">  foo1: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">  &#125;,</span><br><span class="line">  foo2: <span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="built_in">this</span>.name),</span><br><span class="line">  foo3: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  foo4: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> person2 = &#123; <span class="attr">name</span>: <span class="string">&#x27;person2&#x27;</span> &#125;;</span><br><span class="line"></span><br><span class="line">person1.foo1(); <span class="comment">// person1: 隐式调用</span></span><br><span class="line">person1.foo1.call(person2); <span class="comment">// person2: 显示调用,this绑定到person2对象上(显示调用优先级高于隐式调用)</span></span><br><span class="line"></span><br><span class="line">person1.foo2(); <span class="comment">// window: foo2为箭头函数,this指向的是它上级作用域window</span></span><br><span class="line">person1.foo2.call(person2); <span class="comment">// window</span></span><br><span class="line"></span><br><span class="line">person1.foo3()(); <span class="comment">// window: 独立函数调用</span></span><br><span class="line">person1.foo3.call(person2)(); <span class="comment">// window: 独立函数调用</span></span><br><span class="line">person1.foo3().call(person2); <span class="comment">// person2: 显示调用</span></span><br><span class="line"></span><br><span class="line">person1.foo4()(); <span class="comment">// person1, foo4返回箭头函数,this指向的是上级作用域person1</span></span><br><span class="line">person1.foo4.call(person2)(); <span class="comment">// person2: call先将foo4的this绑定到person2上,返回的箭头函数this指向的是person2</span></span><br><span class="line">person1.foo4().call(person2); <span class="comment">// person1</span></span><br></pre></td></tr></table></figure></li>
<li>面试题三<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;window&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span> (<span class="params">name</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.name = name;</span><br><span class="line">  <span class="built_in">this</span>.obj = &#123;</span><br><span class="line">    name: <span class="string">&#x27;obj&#x27;</span>,</span><br><span class="line">    foo1: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    foo2: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> person1 = <span class="keyword">new</span> Person(<span class="string">&#x27;person1&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> person2 = <span class="keyword">new</span> Person(<span class="string">&#x27;person2&#x27;</span>);</span><br><span class="line"></span><br><span class="line">person1.obj.foo1()(); <span class="comment">// window: 独立函数调用</span></span><br><span class="line">person1.obj.foo1.call(person2)(); <span class="comment">// window: 独立函数调用</span></span><br><span class="line">person1.obj.foo1().call(person2); <span class="comment">// person2: 显示调用,将foo1返回的函数的this绑定到person2上</span></span><br><span class="line"></span><br><span class="line">person1.obj.foo2()(); <span class="comment">// obj: 隐式调用,obj.foo2()调用返回箭头函数,因为是通过obj调用,所以箭头函数的this指向的是obj</span></span><br><span class="line">person1.obj.foo2.call(person2)(); <span class="comment">// person2: 显示调用,将foo2的this绑定到person2上,返回的箭头函数this指向的是person2</span></span><br><span class="line">person1.obj.foo2().call(person2); <span class="comment">// obj</span></span><br></pre></td></tr></table></figure>
<h2 id="call-apply-bind的简单实现"><a href="#call-apply-bind的简单实现" class="headerlink" title="call/apply/bind的简单实现"></a>call/apply/bind的简单实现</h2></li>
</ul>
</li>
<li><p>call的简单实现</p>
</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ...args为剩余参数</span></span><br><span class="line"><span class="built_in">Function</span>.prototype.myCall = <span class="function"><span class="keyword">function</span>(<span class="params">thisArg, ...args</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 1. 获取要被执行的函数</span></span><br><span class="line">  <span class="keyword">let</span> fn = <span class="built_in">this</span>;</span><br><span class="line">  <span class="comment">// 只能调用函数,否则抛出错误</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">typeof</span> fn !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;Error&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 2. 判断传入的thisArg的类型,如果为undefined/null直接赋值window</span></span><br><span class="line">  thisArg = (thisArg !== <span class="literal">undefined</span> &amp;&amp; thisArg !== <span class="literal">null</span>) ? <span class="built_in">Object</span>(thisArg) : <span class="built_in">window</span>;</span><br><span class="line">  <span class="comment">// 3. 将要被执行的函数赋值到thisArg上</span></span><br><span class="line">  thisArg.fn = fn;</span><br><span class="line">  <span class="comment">// 4. 执行函数并返回</span></span><br><span class="line">  <span class="keyword">let</span> result = thisArg.fn(...args);</span><br><span class="line">  <span class="keyword">delete</span> thisArg.fn;</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="2">
<li>apply的简单实现</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Function</span>.prototype.myApply = <span class="function"><span class="keyword">function</span>(<span class="params">thisArg, argArray</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 1. 获取要被执行的函数</span></span><br><span class="line">  <span class="keyword">let</span> fn = <span class="built_in">this</span>;</span><br><span class="line">  <span class="comment">// 只能调用函数,否则抛出错误</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">typeof</span> fn !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;Error&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 2. 判断thisArg的类型,如果为undefined或null直接赋值window</span></span><br><span class="line">  thisArg = (thisArg !== <span class="literal">undefined</span> &amp;&amp; thisArg !== <span class="literal">null</span>) ? <span class="built_in">Object</span>(thisArg) : <span class="built_in">window</span>;</span><br><span class="line">  <span class="comment">// 3. 将要被执行的函数赋值到thisArg上</span></span><br><span class="line">  thisArg.fn = fn;</span><br><span class="line">  <span class="comment">// 4. 判断argArray是否有值</span></span><br><span class="line">  <span class="keyword">let</span> result;</span><br><span class="line">  argArray = argArray &amp;&amp; argArray.length ? argArray : [];</span><br><span class="line">  <span class="comment">// 5. 执行函数并返回</span></span><br><span class="line">  result = thisArg.fn(...argArray);</span><br><span class="line">  <span class="keyword">delete</span> thisArg.fn;</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="3">
<li>bind的简单实现</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Function</span>.prototype.myBind = <span class="function"><span class="keyword">function</span>(<span class="params">thisArg, ...<span class="built_in">arguments</span></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 1. 获取要被执行的函数</span></span><br><span class="line">  <span class="keyword">let</span> fn = <span class="built_in">this</span>;</span><br><span class="line">  <span class="comment">// 判断fn是否为函数,不为函数抛出错误</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">typeof</span> fn !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;Error&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 2. 判断thisArg的类型, 如果为undefined或null直接赋值window</span></span><br><span class="line">  thisArg = (thisArg !== <span class="literal">undefined</span> &amp;&amp; thisArg !== <span class="literal">null</span>) ? thisArg : <span class="built_in">window</span>;</span><br><span class="line">  <span class="comment">// 3. 返回一个新函数</span></span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="title">funtion</span>(<span class="params">..args</span>)</span> &#123;</span><br><span class="line">    <span class="comment">// 4. 将被执行函数赋值到thisArg上</span></span><br><span class="line">    thisArg.fn = fn;</span><br><span class="line">    <span class="comment">// 5. 拼接两个函数的参数</span></span><br><span class="line">    <span class="keyword">let</span> allArr = [...arguments, ...args];</span><br><span class="line">    <span class="comment">// 6. 执行函数并返回</span></span><br><span class="line">    <span class="keyword">let</span> result = thisArg.fn(...allArr);</span><br><span class="line">    <span class="keyword">delete</span> thisArg.fn;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol start="4">
<li>call/apply/bind三者的区别</li>
</ol>
<ul>
<li>call、apply和bind的第一个参数作用一致。</li>
<li>call和apply的区别在于call的第二个参数为一个<code>参数列表</code>,而apply的第二个参数为一个<code>数组或类数组</code>。</li>
<li>call和apply会立即调用函数，但bind内部会返回一个新的函数。</li>
</ul>
<h2 id="arguments"><a href="#arguments" class="headerlink" title="arguments"></a>arguments</h2><ol>
<li>arguments是一个对应于传递给函数的参数的<code>类数组对象</code>。</li>
<li>arguments为什么是类数组?</li>
</ol>
<ul>
<li>它拥有数组的一些特性,比如length、可以通过index索引获取值。</li>
<li>但是没有数组的一些方法,比如forEach、map等。</li>
</ul>
<ol start="3">
<li>将arguments转成数组的方法</li>
</ol>
<ul>
<li>通过for循环遍历,将遍历的各个项push到一个新数组中。</li>
<li>通过<code>Array.prototype.slice.call(arguments)</code>或[].slice.call(arguments)。</li>
<li>通过ES6语法<code>Array.from(arguments)</code>。</li>
<li>通过展开运算符: <code>[...arguments]</code>。</li>
</ul>
<h2 id="JavaScript纯函数"><a href="#JavaScript纯函数" class="headerlink" title="JavaScript纯函数"></a>JavaScript纯函数</h2><ol>
<li>纯函数定义:</li>
</ol>
<ul>
<li>相同的输入,一定会产生相同的输出。</li>
<li>函数在执行过程中,不能产生<code>副作用</code>。</li>
<li><code>副作用</code>表示在执行一个函数时,除了<code>返回函数值</code>之外,还对调用函数产生了附加的影响,比如<code>修改了全局变量</code>,<code>修改参数或者改变外部的存储</code>。</li>
</ul>
<h2 id="JavaScript柯里化"><a href="#JavaScript柯里化" class="headerlink" title="JavaScript柯里化"></a>JavaScript柯里化</h2><ol>
<li>柯里化定义:</li>
</ol>
<ul>
<li>只<code>传递函数的一部分参数</code>来调用它,让它<code>返回一个函数去处理剩余的参数</code>;</li>
<li>这个过程就称之为柯里化</li>
</ul>
<ol start="2">
<li>柯里化的过程<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo1</span>(<span class="params">x, y, z</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> x + y + z;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 等价于</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo2</span>(<span class="params">x</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">y</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">z</span>) </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> x + y + z;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 等价于</span></span><br><span class="line"><span class="keyword">var</span> result3 = <span class="function"><span class="params">x</span> =&gt;</span> <span class="function"><span class="params">y</span> =&gt;</span> <span class="function"><span class="params">z</span> =&gt;</span> x + y + z;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> result1 = foo1(<span class="number">10</span>, <span class="number">20</span>, <span class="number">30</span>);</span><br><span class="line"><span class="keyword">var</span> result2 = foo2(<span class="number">10</span>)(<span class="number">20</span>)(<span class="number">30</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(result1, result2, result3(<span class="number">10</span>)(<span class="number">20</span>)(<span class="number">30</span>)); <span class="comment">// 60 60 60</span></span><br></pre></td></tr></table></figure></li>
<li>柯里化的作用</li>
</ol>
<ul>
<li>让<code>一个函数处理的问题尽可能的单一</code>,而不是将<code>一大堆的处理过程交给单个函数来处理</code>。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">x</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 处理逻辑</span></span><br><span class="line">  x = x + <span class="number">2</span>;</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">y</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 处理逻辑</span></span><br><span class="line">    y = y * <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">z</span>) </span>&#123;</span><br><span class="line">      <span class="comment">// 处理逻辑</span></span><br><span class="line">      z = z - <span class="number">2</span>;</span><br><span class="line">      <span class="keyword">return</span> x + y + z;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">sum(<span class="number">10</span>)(<span class="number">20</span>)(<span class="number">30</span>);</span><br></pre></td></tr></table></figure></li>
<li>逻辑的复用性<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> log = <span class="function"><span class="params">date</span> =&gt;</span> <span class="function"><span class="params">type</span> =&gt;</span> <span class="function"><span class="params">message</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;date.getHours()&#125;</span>:<span class="subst">$&#123;date.getMinutes()&#125;</span>-<span class="subst">$&#123;type&#125;</span>: <span class="subst">$&#123;message&#125;</span>`</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 避免多次调用,固定传参重复书写</span></span><br><span class="line"><span class="keyword">var</span> nowLog = log(<span class="keyword">new</span> <span class="built_in">Date</span>());</span><br><span class="line">nowLog(<span class="string">&#x27;debug&#x27;</span>)(<span class="string">&#x27;出错了&#x27;</span>); <span class="comment">// 22:52-debug: 出错了</span></span><br><span class="line">nowLog(<span class="string">&#x27;debug&#x27;</span>)(<span class="string">&#x27;连接服务器失败&#x27;</span>); <span class="comment">// 22:52-debug: 连接服务器失败</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> nowTypeLog = log(<span class="keyword">new</span> <span class="built_in">Date</span>())(<span class="string">&#x27;debug&#x27;</span>);</span><br><span class="line">nowTypeLog(<span class="string">&#x27;出错了&#x27;</span>); <span class="comment">// 22:52-debug: 出错了</span></span><br><span class="line">nowTypeLog(<span class="string">&#x27;连接服务器失败&#x27;</span>); <span class="comment">// 22:52-debug: 连接服务器失败</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="4">
<li>函数柯里化的简单实现<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">myCurrying</span>(<span class="params">fn</span>) </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">curried</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 1. 当传入的参数 大于等于 需要的参数时, 就执行函数</span></span><br><span class="line">    <span class="keyword">if</span> (args.length &gt;= fn.length) &#123;</span><br><span class="line">      <span class="comment">// return fn.call(this, ...args);</span></span><br><span class="line">      <span class="keyword">return</span> fn.apply(<span class="built_in">this</span>, args);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">// 当没有达到时,需要返回一个新的函数,继续接收参数</span></span><br><span class="line">      <span class="function"><span class="keyword">function</span> <span class="title">curried2</span>(<span class="params">...args2</span>) </span>&#123;</span><br><span class="line">        <span class="comment">// 接收到参数后,进行递归调用curried,直到满足条件</span></span><br><span class="line">        <span class="keyword">return</span> curried.apply(<span class="built_in">this</span>, [...args, ...args2]);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> curried2;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> curried;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li>组合函数</li>
</ol>
<ul>
<li>组合函数是在JavaScript开发过程中的一种对<code>函数使用的技巧、模式</code>:<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">composite</span>(<span class="params">fn1, fn2</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">x</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> fn2(fn1(x));</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> num + <span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">square</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> num ** <span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> calcFn = composite(add, square);</span><br><span class="line">calcFn(<span class="number">2</span>); <span class="comment">// 16</span></span><br></pre></td></tr></table></figure></li>
<li>组合函数的简单实现<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 传入多个函数,所以需要用剩余运算符</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">compositeFns</span>(<span class="params">...fns</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 判断传入的类型,如果不为函数类型,提示错误</span></span><br><span class="line">  <span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; fns.length; i++) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> fns[i] !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">throw</span> <span class="built_in">TypeError</span>(<span class="string">&#x27;Error, type is not function&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 该函数接收传入的参数,并返回</span></span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">composite</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">var</span> result = fns.length ? fns[index].apply(<span class="built_in">this</span>, args) : args;</span><br><span class="line">    <span class="keyword">while</span>(++index &lt; length) &#123;</span><br><span class="line">      result = fns[index].call(<span class="built_in">this</span>, result);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> composite;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="JavaScript面向对象"><a href="#JavaScript面向对象" class="headerlink" title="JavaScript面向对象"></a>JavaScript面向对象</h2></li>
</ul>
<ol>
<li>属性描述符</li>
</ol>
<ul>
<li>通过属性描述符可以<code>精准的添加或修改对象的属性</code>。</li>
<li>属性描述符需要使用<code>Object.defineProperty</code>来对属性进行添加或修改。</li>
<li>Object.defineProperty(obj, prop, descriptor);可接收三个参数:<ol>
<li>obj: 要定义属性的对象;</li>
<li>prop: 要定义或修改的属性的名称或Symbol;</li>
<li>descriptor: 要定义或修改的属性描述符;</li>
</ol>
</li>
<li>属性描述符的类型有两种:<ol>
<li><code>数据属性</code>描述符</li>
<li><code>存取属性</code>描述符</li>
</ol>
</li>
<li>数据描述符有如下四个特性:<ol>
<li><code>[[Configurable]]</code>: 表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将他修改为存取属性描述符。（是否可配置的）</li>
</ol>
<ul>
<li>当直接在一个对象上定义某个属性时,这个属性的<code>[[Configurable]]</code>默认为true;</li>
<li>当通过属性描述符定义一个属性时,这个属性的<code>[[Configurable]]</code>默认为false;</li>
</ul>
<ol start="2">
<li><code>[[Enumerable]]</code>: 表示属性是否可以通过for-in或Object.keys()返回该属性。</li>
</ol>
<ul>
<li>当直接在一个对象上定义某个属性时,这个属性的<code>[[Enumerable]]</code>默认为true;</li>
<li>当通过属性描述符定义一个属性时,这个属性的<code>[[Enumerable]]</code>默认为false;</li>
</ul>
<ol start="3">
<li><code>[[Writable]]</code>: 表示是否可以修改属性的值</li>
</ol>
<ul>
<li>当直接在一个对象上定义某个属性时,这个属性的<code>[[Writable]]</code>默认为true;</li>
<li>当通过属性描述符定义一个属性时,这个属性的<code>[[Writable]]</code>默认为false;</li>
</ul>
<ol start="4">
<li><code>[[value]]</code>: 属性的value值,读取属性时会返回该值,修改属性时,会对其进行修改;</li>
</ol>
<ul>
<li>默认情况下这个值为undefined</li>
</ul>
</li>
<li>存取属性描述符有如下特性:<ol>
<li>隐藏某一个私有属性不希望直接被外界使用和赋值</li>
<li>如果希望截获某一个属性它的访问和设置值的过程时,也会使用存取属性描述符<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span>,</span><br><span class="line">  _address: <span class="string">&#x27;广州市&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.defineProperty(obj, <span class="string">&#x27;address&#x27;</span>, &#123;</span><br><span class="line">  enumerable: <span class="literal">true</span>,</span><br><span class="line">  configurable: <span class="literal">true</span>,</span><br><span class="line">  <span class="comment">// 获取值</span></span><br><span class="line">  get: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span>._address</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 接收值并修改</span></span><br><span class="line">  set: <span class="function"><span class="keyword">function</span>(<span class="params">value</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">this</span>._address = value;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(obj._address); <span class="comment">// 广州市</span></span><br><span class="line">obj._address = <span class="string">&#x27;赤壁市&#x27;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(obj._address); <span class="comment">// 赤壁市</span></span><br></pre></td></tr></table></figure></li>
</ol>
</li>
<li>私有属性补充: 如果以_下划线开头定义的属性,统一规范为私有属性。</li>
<li>给对象定义多个属性描述符, <code>Object.defineProperties()</code>。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  _age: <span class="number">18</span>,</span><br><span class="line">  <span class="comment">// 这种写法默认configurable和enumerable为true</span></span><br><span class="line">  <span class="keyword">get</span> <span class="title">age</span>() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span>._age;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">set</span> <span class="title">age</span>(<span class="params">value</span>)&#123;</span><br><span class="line">    <span class="built_in">this</span>._age = value;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">Object</span>.defineProperties(obj, &#123;</span><br><span class="line">  name: &#123;</span><br><span class="line">    configurable: <span class="literal">true</span>,</span><br><span class="line">    enumerable: <span class="literal">true</span>,</span><br><span class="line">    writable: <span class="literal">true</span>,</span><br><span class="line">    value: <span class="string">&quot;wbw&quot;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 这种写法可以更精准的控制configurable和enumerable</span></span><br><span class="line">  age: &#123;</span><br><span class="line">    configurable: <span class="literal">true</span>,</span><br><span class="line">    enumerable: <span class="literal">true</span>,</span><br><span class="line">    get: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="built_in">this</span>._age</span><br><span class="line">    &#125;</span><br><span class="line">    set: <span class="function"><span class="keyword">function</span>(<span class="params">value</span>) </span>&#123;</span><br><span class="line">      <span class="built_in">this</span>._age = value;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="2">
<li>创建对象的方法</li>
</ol>
<ul>
<li>工厂模式(缺点: 打印对象的时,类型都为Object类型,无法拿到具体的类型)<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createPerson</span>(<span class="params">name, age, height</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> p = &#123;&#125;;</span><br><span class="line">  p.name = name;</span><br><span class="line">  p.age = age;</span><br><span class="line">  p.height = height;</span><br><span class="line">  p.eating = <span class="function"><span class="title">functon</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span>在吃东西`</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> p;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> p1 = createPerson(<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>, <span class="number">178</span>);</span><br></pre></td></tr></table></figure></li>
<li>构造函数<ol>
<li>通过new关键字去调用一个函数时,那么这个函数就是一个构造函数。</li>
<li>如果一个函数被使用new操作符调用了,那么它会执行以下步骤:</li>
</ol>
<ul>
<li>在内存中创建一个新的对象(空对象);</li>
<li>这个对象内部的<code>[[prototype]]</code>属性会被赋值为该构造函数的<code>prototype</code>属性;</li>
<li>构造函数内部的this,会指向创建出来的新对象;</li>
<li>指向函数的内部代码(函数体代码);</li>
<li>如果构造函数没有返回非空对象,则返回创建出来的新对象;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age, height</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.name = name;</span><br><span class="line">  <span class="built_in">this</span>.age = age;</span><br><span class="line">  <span class="built_in">this</span>.height = height;</span><br><span class="line">  <span class="comment">// this.eating = function() &#123;</span></span><br><span class="line">  <span class="comment">//  console.log(`$&#123;this.name&#125;在吃东西`);</span></span><br><span class="line">  <span class="comment">// &#125;</span></span><br><span class="line">&#125;</span><br><span class="line">Person.prototype.eating = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span>在吃东西`</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> p1 = <span class="keyword">new</span> Person(<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>, <span class="number">178</span>);</span><br><span class="line">p1.eating();</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li>对象的原型<ol>
<li>每个对象(实例对象)中都有一个<code>[[prototype]]</code>属性(即<strong>proto</strong>),这个属性指向的是原型对象(隐式原型)。</li>
<li>每个构造函数中都有一个prototype属性,这个属性指向的是原型对象(显示原型)。</li>
<li>给原型对象上添加属性或方法<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Foo</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line"><span class="comment">// 方式一,添加多个属性或方法时,重复写多次Foo.prototype,可以使用方式二</span></span><br><span class="line">Foo.prototype.name = <span class="string">&#x27;wbw&#x27;</span>;</span><br><span class="line">Foo.prototype.age = <span class="number">18</span>;</span><br><span class="line">Foo.prototype.eating = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;Foo.prototype.name&#125;</span>在吃东西`</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 方式二,重写原型对象</span></span><br><span class="line">Foo.prototype = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span>,</span><br><span class="line">  eating = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 因为原型对象上默认会有一个constructor,且不可枚举</span></span><br><span class="line"><span class="built_in">Object</span>.definProperty(Foo.prototype, <span class="string">&#x27;constructor&#x27;</span>, &#123;</span><br><span class="line">  enumerable: <span class="literal">false</span>,</span><br><span class="line">  configurable: <span class="literal">true</span>,</span><br><span class="line">  writable: <span class="literal">true</span>,</span><br><span class="line">  value: Foo</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></li>
</ol>
</li>
</ul>
<ol start="3">
<li>Object的原型</li>
</ol>
<ul>
<li>什么地方是原型链的尽头?<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj = &#123;&#125;;</span><br><span class="line"><span class="built_in">console</span>.log(obj.__proto__.__proto__.__proto__); <span class="comment">// 打印的结果为[Object: null prototype] &#123;&#125;</span></span><br><span class="line"><span class="comment">// 1. 事实上[Object: null prototype] &#123;&#125;这个原型就是最顶层的原型</span></span><br><span class="line"><span class="comment">// 2. 从Object直接创建出来的对象的原型都是[Object: null prototype] &#123;&#125;</span></span><br></pre></td></tr></table></figure></li>
<li>[Object: null prototype] {}原型有什么特殊吗?<ol>
<li>特殊一: 该对象有原型对象，但是通过__proto__指向的已经为null,也就是已经是顶层原型了;</li>
<li>特殊二: 该对象上有很多默认的属性和方法;</li>
</ol>
</li>
<li><code>原型链最顶端的原型对象就是Object的原型对象</code>;<br><a target="_blank" rel="noopener" href="https://imgtu.com/i/T6CwOe"><img src="https://s4.ax1x.com/2021/12/28/T6CwOe.png" alt="T6CwOe.png"></a></li>
</ul>
<ol start="4">
<li>原型链继承</li>
</ol>
<ul>
<li>弊端一: 打印stu对象，继承的属性不可见。</li>
<li>弊端二: 创建出两个对象,获取引用时,如果修改了引用中的值,会相互影响。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> stu1 = <span class="keyword">new</span> Son();</span><br><span class="line"><span class="keyword">let</span> stu2 = <span class="keyword">new</span> Son();</span><br><span class="line"></span><br><span class="line">stu1.friend.push(<span class="string">&#x27;lxd&#x27;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(stu1.friend); <span class="comment">// [&#x27;lxd&#x27;]</span></span><br><span class="line"><span class="built_in">console</span>.log(stu2.friend); <span class="comment">// [&#x27;lxd&#x27;]</span></span><br></pre></td></tr></table></figure></li>
<li>弊端三: 实现类的过程中没有传递参数,且不好处理传参问题。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 父类</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.name = <span class="string">&#x27;wbw&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Person.prototype.eating = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span> 在吃东西`</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 子类</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Son</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.age = <span class="number">18</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 这两句代码顺序不能错, 如果写在Son.prototype.studing下面,那么studing方法会在Son之前的原型对象上</span></span><br><span class="line">Son.prototype = <span class="keyword">new</span> Person(); <span class="comment">// 将Person的实例赋值给Son的原型</span></span><br><span class="line">Son.prototype.studing = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.name&#125;</span> 在学习`</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> son = <span class="keyword">new</span> Son();</span><br><span class="line"><span class="built_in">console</span>.log(son.name); <span class="comment">// 打印结果为wbw</span></span><br><span class="line">son.eating(); <span class="comment">// 打印结果为wbw 在吃东西</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="5">
<li>借用构造函数<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">* 弊端一: 父类构造函数Person至少会被执行两次</span></span><br><span class="line"><span class="comment">* 弊端二: son实例对象的原型上多出不必要的属性,这些属性不应该存在</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age, friend</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.name = name;</span><br><span class="line">  <span class="built_in">this</span>.age = age;</span><br><span class="line">  <span class="built_in">this</span>.friend = friend;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Person.prototype.eating = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">this</span>.name + <span class="string">&#x27;在吃东西&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Son</span>(<span class="params">name, age, friend, number</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 借用父类容器,给每个Son构造函数new出来的实例添加对应的属性</span></span><br><span class="line">  Person.call(<span class="built_in">this</span>, name, age, friend);</span><br><span class="line">  <span class="built_in">this</span>.number = number;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 这里还是通过原型链将父类的实例赋值给子类的原型</span></span><br><span class="line">Son.prototype = <span class="keyword">new</span> Person();</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> son1 = <span class="keyword">new</span> Son(<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>, [<span class="string">&#x27;lxd&#x27;</span>], <span class="number">111</span>);</span><br><span class="line"><span class="keyword">let</span> son2 = <span class="keyword">new</span> Son(<span class="string">&#x27;lxd&#x27;</span>, <span class="number">18</span>, [<span class="string">&#x27;wbw&#x27;</span>], <span class="number">222</span>);</span><br><span class="line">son1.friend.push(<span class="string">&#x27;qqq&#x27;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(son1.friend); <span class="comment">// [&#x27;lxd&#x27;, &#x27;qqq&#x27;]</span></span><br><span class="line"><span class="built_in">console</span>.log(son1.friend); <span class="comment">// [&#x27;wbw&#x27;]</span></span><br></pre></td></tr></table></figure></li>
<li>原型式继承</li>
</ol>
<ul>
<li>弊端: 还是需要手动给每个对象添加属性或方法,如果每个对象的部分属性相同,代码显得比较冗余,不灵活。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 写法一</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createObject1</span>(<span class="params">o</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> newObj = &#123;&#125;;</span><br><span class="line">  <span class="comment">// 第一个参数为要设置其原型的对象,第二个参数为对象的新原型(对象或null)</span></span><br><span class="line">  <span class="built_in">Object</span>.setPrototypeOf(newObj, o);</span><br><span class="line">  <span class="keyword">return</span> newObj;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> c = createObject1(obj);</span><br><span class="line"><span class="built_in">console</span>.log(c); <span class="comment">// &#123;&#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(c.__proto__); <span class="comment">// &#123;name: &#x27;wbw&#x27;, age: 18&#125;</span></span><br><span class="line"><span class="comment">// 写法二</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createObject2</span>(<span class="params">o</span>) </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">Fn</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line">  Fn.prototype = o;</span><br><span class="line">  <span class="keyword">var</span> newObj = <span class="keyword">new</span> Fn();</span><br><span class="line">  <span class="keyword">return</span> newObj;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> c = createObject2(obj);</span><br><span class="line"><span class="built_in">console</span>.log(c); <span class="comment">// &#123;&#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(c.__proto__); <span class="comment">// &#123;name: &#x27;wbw&#x27;, age: 18&#125;</span></span><br><span class="line"><span class="comment">// 写法三</span></span><br><span class="line"><span class="keyword">var</span> c = <span class="built_in">Object</span>.create(obj);</span><br><span class="line"><span class="built_in">console</span>.log(c); <span class="comment">// &#123;&#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(c.__proto__); <span class="comment">// &#123;name: &#x27;wbw&#x27;, age: 18&#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="7">
<li>寄生组合式继承(最完善的方法)<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createObject</span>(<span class="params">o</span>) </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">Fn</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line">  Fn.prototype = o;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> Fn();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">inheritProperty</span>(<span class="params">SubType, SupType</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 创建一个新的构造函数,将父类的原型赋值给新构造函数的原型,返回该构造函数的实例并赋值给子类原型。避免了修改了子类型原型对象的某个引用类型的时候, 父类型原生对象的引用类型也会被修改的问题。</span></span><br><span class="line">  SubType.prototype = createObject(SupType.prototype);</span><br><span class="line">  <span class="comment">// SubType.prototype = Object.create(SupType.prototype);</span></span><br><span class="line">  <span class="comment">// 将子类原型的constructor重新指回子类构造函数</span></span><br><span class="line">  <span class="built_in">Object</span>.defineProperty(SubType.prototype, <span class="string">&#x27;constructor&#x27;</span>, &#123;</span><br><span class="line">    configurable: <span class="literal">true</span>,</span><br><span class="line">    enumerable: <span class="literal">false</span>,</span><br><span class="line">    writable: <span class="literal">false</span>,</span><br><span class="line">    value: SubType</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age, friend</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.name = name;</span><br><span class="line">  <span class="built_in">this</span>.age = age;</span><br><span class="line">  <span class="built_in">this</span>.friend = friend;</span><br><span class="line">&#125;</span><br><span class="line">Person.prototype.studing = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  cosnole.log(<span class="string">&#x27;studing~&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line">Person.prototype.running = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;running~&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Student</span>(<span class="params">name, age, friend, num, score</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 通过call继承父类构造函数Person的属性</span></span><br><span class="line">  Person.call(<span class="built_in">this</span>, name, age, friend);</span><br><span class="line">  <span class="built_in">this</span>.num = num;</span><br><span class="line">  <span class="built_in">this</span>.score = score;</span><br><span class="line">&#125;</span><br><span class="line">Student.prototype.eating = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;eating~&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">inheritPrototype(Student, Person);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> stu = <span class="keyword">new</span> Student(<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>, [<span class="string">&#x27;lxd&#x27;</span>], <span class="number">1</span>, <span class="number">100</span>);</span><br><span class="line"><span class="built_in">console</span>.log(stu); <span class="comment">// Student &#123; name: &#x27;wbw&#x27;, age: 18, friend: [&#x27;lxd&#x27;], num: 1, score: 100 &#125;</span></span><br><span class="line">stu.studing(); <span class="comment">// studing~</span></span><br><span class="line">stu.running(); <span class="comment">// running~</span></span><br><span class="line">stu.eating(); <span class="comment">// eating~</span></span><br></pre></td></tr></table></figure></li>
<li>原型-判断方法的补充</li>
</ol>
<ul>
<li><code>hasOwnProperty()方法</code>: 判断该对象上的属性是否是自身属性而不是原型上的。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * Object.create()方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__</span></span><br><span class="line"><span class="comment"> * 第一个参数为新创建对象的原型对象</span></span><br><span class="line"><span class="comment"> * 第二个参数和defineProperty()方法类似,通过属性描述符在新对象上添加属性。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">var</span> info = <span class="built_in">Object</span>.create(obj, &#123;</span><br><span class="line">  address: &#123;</span><br><span class="line">    value: <span class="string">&#x27;广州市&#x27;</span>,</span><br><span class="line">    enumerable: <span class="literal">true</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="built_in">console</span>.log(info.hasOwnProperty(<span class="string">&#x27;address&#x27;</span>)); <span class="comment">// true</span></span><br><span class="line"><span class="built_in">console</span>.log(info.hasOwnProperty(<span class="string">&#x27;name&#x27;</span>)); <span class="comment">// false</span></span><br></pre></td></tr></table></figure></li>
<li><code>in操作符</code>: 不管在当前对象还是当前对象的原型上都返回true</li>
<li><code>instanceof</code>: 用于检测<code>构造函数的prototype</code>,是否出现在<code>某个实例对象的原型链</code>上</li>
</ul>
<ol start="9">
<li><p>原型继承关系</p>
<p><a target="_blank" rel="noopener" href="https://imgtu.com/i/y6hltg"><img src="https://z3.ax1x.com/2021/02/15/y6hltg.png" alt="y6hltg.png"></a></p>
</li>
</ol>
<h2 id="ES6中类的使用"><a href="#ES6中类的使用" class="headerlink" title="ES6中类的使用"></a>ES6中类的使用</h2><ol>
<li>class的构造方法</li>
</ol>
<ul>
<li>每个类都可以有一个自己的构造函数(方法),这个方法的名称是固定的constructor;</li>
<li>通过new操作符,操作一个类的时候会调用这个类的构造函数constructor;</li>
<li>每个类只有一个构造函数,如果包含多个构造函数,那么会抛出异常;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name, age</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">    <span class="built_in">this</span>.age = age;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> p1 = <span class="keyword">new</span> Person(<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>);</span><br><span class="line"><span class="built_in">console</span>.log(p1); <span class="comment">// Person &#123; name: &#x27;wbw&#x27;, age: 18 &#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="2">
<li>class中的方法定义<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name, age</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">    <span class="built_in">this</span>.age = age;</span><br><span class="line">    <span class="built_in">this</span>._address = <span class="string">&#x27;广州市&#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 定义普通的实例方法</span></span><br><span class="line">  <span class="comment">//  通过创建出来的对象进行访问的</span></span><br><span class="line">  <span class="function"><span class="title">eating</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name + <span class="string">&#x27;eating!&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 类的访问器方法</span></span><br><span class="line">  <span class="comment">//  通过创建出来的对象进行访问的</span></span><br><span class="line">  <span class="keyword">get</span> <span class="title">address</span>() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span>._address;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">set</span> <span class="title">address</span>(<span class="params">newAddress</span>) &#123;</span><br><span class="line">    <span class="built_in">this</span>._address = newAddress;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 类的静态方法</span></span><br><span class="line">  <span class="comment">// 通过类名访问,Person.createPerson()</span></span><br><span class="line">  <span class="keyword">static</span> <span class="function"><span class="title">createPerson</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;静态方法调用成功&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> p = <span class="keyword">new</span> Person(<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>);</span><br><span class="line"><span class="built_in">console</span>.log(p.eating()); <span class="comment">// eating!</span></span><br><span class="line"><span class="built_in">console</span>.log(p._address); <span class="comment">// 广州市</span></span><br><span class="line">p._address = <span class="string">&#x27;深圳市&#x27;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(p._address); <span class="comment">// 深圳市</span></span><br><span class="line"><span class="keyword">var</span> pp = Person.createPerson(); <span class="comment">// 静态方法调用成功</span></span><br></pre></td></tr></table></figure></li>
<li>class中实现继承extends</li>
</ol>
<ul>
<li>super关键字使用方法:<ul>
<li>在子类的构造函数中<code>使用this或者返回默认对象之前</code>,<code>必须先通过super调用父类的构造函数</code>;</li>
<li>super的使用位置有三个: 子类的构造函数、实例方法、静态方法;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name, age</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">    <span class="built_in">this</span>.age = age;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="title">running</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">this</span>.name + <span class="string">&#x27;running&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  <span class="function"><span class="title">FaMethod</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;1&#x27;</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;2&#x27;</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;3&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> <span class="function"><span class="title">staticMethod</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;static&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span> <span class="keyword">extends</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name, age, address</span>)</span> &#123;</span><br><span class="line">    <span class="comment">// 调用父对象/父类的构造函数: super([arguments])</span></span><br><span class="line">    <span class="built_in">super</span>(name, age);</span><br><span class="line">    <span class="built_in">this</span>.address = address;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 子类对父类方法的重写</span></span><br><span class="line">  <span class="function"><span class="title">running</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;Student &#x27;</span> + <span class="built_in">this</span>.name + <span class="string">&#x27; running&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 子类对父类方法的重写，但保留父类的方法: super.xxx([arguments])</span></span><br><span class="line">  <span class="function"><span class="title">FaMethod</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">super</span>.FaMethod();</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;4&#x27;</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;5&#x27;</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;6&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 子类重写父类的静态方法</span></span><br><span class="line">  <span class="keyword">static</span> <span class="function"><span class="title">staticMethod</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">super</span>.staticMethod();</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;static1&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> stu = <span class="keyword">new</span> Student(<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>, <span class="string">&#x27;广州市&#x27;</span>);</span><br><span class="line">stu.running(); <span class="comment">// Student wbw running</span></span><br><span class="line">stu.FaMethod(); <span class="comment">// 1 2 3 4 5 6</span></span><br><span class="line">Student.staticMethod(); <span class="comment">// static static1 </span></span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<ol start="4">
<li>JavaScript中的多态</li>
</ol>
<ul>
<li>不同的数据类型进行同一个操作,表现出不同的行为,就是多态的体系。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">n, m</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> n + m;</span><br><span class="line">&#125;</span><br><span class="line">sum(<span class="number">1</span>, <span class="number">2</span>); <span class="comment">// 3</span></span><br><span class="line">sum(<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>) <span class="comment">// &#x27;12&#x27;</span></span><br></pre></td></tr></table></figure>
<h2 id="ES6知识点"><a href="#ES6知识点" class="headerlink" title="ES6知识点"></a>ES6知识点</h2></li>
</ul>
<ol>
<li>解构赋值</li>
</ol>
<ul>
<li>数组的解构<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = [<span class="string">&quot;wbw&quot;</span>, <span class="string">&quot;lxd&quot;</span>, <span class="string">&quot;kiko&quot;</span>];</span><br><span class="line"><span class="comment">// 解构数组全部元素</span></span><br><span class="line"><span class="keyword">var</span> [item1, item2, item3] = name;</span><br><span class="line"><span class="built_in">console</span>.log(item1, item2, item3); <span class="comment">// wbw lxd kiko</span></span><br><span class="line"><span class="comment">// 解构指定数组元素</span></span><br><span class="line"><span class="keyword">var</span> [, itema, itemb] = name;</span><br><span class="line"><span class="built_in">console</span>.log(itema, itemb); <span class="comment">// lxd kiko</span></span><br><span class="line"><span class="comment">// 解构的默认值</span></span><br><span class="line"><span class="keyword">var</span> [a, b, c, d = <span class="string">&#x27;dyz&#x27;</span>] = name;</span><br><span class="line"><span class="built_in">console</span>.log(d); <span class="comment">// dyz</span></span><br></pre></td></tr></table></figure></li>
<li>对象的解构<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> &#123; name, age &#125; = obj;</span><br><span class="line"><span class="built_in">console</span>.log(name, age); <span class="comment">// wbw 18</span></span><br><span class="line"><span class="comment">// 对解构名重新命名</span></span><br><span class="line"><span class="keyword">var</span> &#123; <span class="attr">name</span>: newName &#125; = obj;</span><br><span class="line"><span class="built_in">console</span>.log(newName); <span class="comment">// wbw</span></span><br><span class="line"><span class="comment">// 解构的默认值</span></span><br><span class="line"><span class="keyword">var</span> &#123; address = <span class="string">&#x27;广州市&#x27;</span> &#125; = obj;</span><br><span class="line"><span class="built_in">console</span>.log(address); <span class="comment">// 广州市</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="2">
<li>let-const的基本使用</li>
</ol>
<ul>
<li>注意事项一: <code>const</code>本质是传递的值不可以修改,但是如果传递的是一个引用类型(内存地址),可以通过引用找到对应的对象,去修改对象内部的属性。</li>
<li>注意事项二: <code>let/const</code>定义的变量名是不可以重复定义的</li>
</ul>
<ol start="3">
<li>let/const有没有作用域提升?</li>
</ol>
<ul>
<li><code>作用域提升</code>: 在声明变量的作用域中,如果这个变量可以在声明之前被访问,可以称之为变量提升</li>
<li>但是<code>let/cons</code>t在声明前无法访问到变量,所以没有进行作用域提升,但是会在执行上下文阶段被创建出来。</li>
<li>全局通过var来声明的变量,会在Window上添加一个属性;但是let、const是不会在window上添加任何属性的。</li>
</ul>
<ol start="4">
<li>ES6的块级作用域</li>
</ol>
<ul>
<li>对于let/const/function/class声明的类型是有效的<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> foo = <span class="string">&#x27;foo&#x27;</span>;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">demo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;demo function&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(foo); <span class="comment">// foo is not defined</span></span><br><span class="line"><span class="comment">// 函数比较特殊,(大部分浏览器为了兼容旧版本,使得function没有块级作用域)</span></span><br><span class="line">demo(); <span class="comment">// demo function</span></span><br><span class="line"><span class="keyword">var</span> p = <span class="keyword">new</span> Person(); <span class="comment">// Person is not defined</span></span><br></pre></td></tr></table></figure></li>
<li>if语句/switch语句/for循环都是<code>块级作用域</code></li>
<li><code>暂时性死区</code>: 使用let、const声明的变量,在声明之前,变量都是不可以访问的</li>
</ul>
<ol start="5">
<li>let、const的选择</li>
</ol>
<ul>
<li>优先使用const,可以保证数据的安全性,不会被随意。</li>
<li>只有当明确知道一个变量后续需要被重新赋值时,再去使用let。</li>
</ul>
<ol start="6">
<li>标签模板字符串<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 第一个参数是模块字符串中整个字符串,会被分成多块,放入数组中</span></span><br><span class="line"><span class="comment">// 第二个参数是模板字符串中,第一个$&#123;&#125;里的值,以此类推</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">m, n</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(m, n); <span class="comment">// [&#x27;Hello&#x27;, &#x27;World&#x27;] wbw</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> name = <span class="string">&#x27;wbw&#x27;</span>;</span><br><span class="line">foo<span class="string">`Hello<span class="subst">$&#123;name&#125;</span>World`</span></span><br></pre></td></tr></table></figure></li>
<li>函数默认参数<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 一般情况</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">m = <span class="string">&#x27;wbw&#x27;</span>, n = <span class="string">&#x27;lxd&#x27;</span></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(m, n);</span><br><span class="line">&#125;</span><br><span class="line">foo(); <span class="comment">// wbw lxd</span></span><br><span class="line"><span class="comment">// 默认值为对象</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params">obj = &#123; name: <span class="string">&#x27;wbw&#x27;</span>, age: <span class="number">18</span> &#125;</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(obj.name, obj.age);</span><br><span class="line">&#125;</span><br><span class="line">bar(); <span class="comment">// wbw 18</span></span><br></pre></td></tr></table></figure></li>
</ol>
<ul>
<li>有默认值的形参最好放最后面</li>
<li>有默认值的函数的length,该形参(包括)之后的都不会计算再函数长度内<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">a, b, c = <span class="number">2</span>, d</span>) </span>&#123;&#125;</span><br><span class="line"><span class="built_in">console</span>.log(foo.length); <span class="comment">// 2</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="8">
<li>函数剩余参数</li>
</ol>
<ul>
<li>如果最后一个参数是…为前缀,那么它会将剩余的参数放到该参数中,并作为一个数组<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">m, n, ...args</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(m, n); <span class="comment">// 1 2</span></span><br><span class="line">  <span class="built_in">console</span>.log(args); <span class="comment">// [3, 4, 5]</span></span><br><span class="line">&#125;</span><br><span class="line">foo(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>);</span><br></pre></td></tr></table></figure></li>
<li>剩余参数和arguments的区别?<ul>
<li>剩余参数只包含那些<code>没有对应形参的实参</code>,而arguments对象包含了<code>传给函数的所有实参</code>;</li>
<li>剩余参数是一个真正的数组，arguments只是一个类数组,不具有数组的方法;</li>
<li>剩余参数必须放到最后一个位置,否则会报错。</li>
</ul>
</li>
</ul>
<ol start="9">
<li>展开运算符的三种场景的使用</li>
</ol>
<ul>
<li>函数调用时使用</li>
<li>将两个数组拼接时使用</li>
<li>构建对象字面量时使用</li>
<li><code>展开运算符会进行浅拷贝</code>,只对第一层进行拷贝,内部的数组或对象仅仅是将引用地址进行赋值,会互相影响。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> info = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span>,</span><br><span class="line">  friend: &#123;</span><br><span class="line">    name: <span class="string">&#x27;lxd&#x27;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">const</span> obj = &#123;...info, <span class="attr">address</span>: <span class="string">&#x27;广州市&#x27;</span>&#125;;</span><br><span class="line"><span class="built_in">console</span>.log(info); <span class="comment">// &#123;name: &#x27;wbw&#x27;, age: 18, friend: &#123;name: &#x27;lxd&#x27;&#125;&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 当一方的friend变化时,另一个对象中的friend也会发生改变</span></span><br><span class="line">obj.friend.name = <span class="string">&#x27;kiko&#x27;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(info); <span class="comment">// &#123;name: &#x27;wbw&#x27;, age: 18, friend: &#123;name: &#x27;kiko&#x27;&#125;&#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="10">
<li>Symbol的基本使用</li>
</ol>
<ul>
<li>Symbol用来<code>生成一个独一无二的值</code>;<ul>
<li>Symbol值是通过Symbol函数来生成的,生成后可以作为<code>属性名</code>;</li>
<li>在ES6中,对象的属性名可以<code>使用字符串</code>,也可以<code>使用Symbol值</code>;</li>
</ul>
</li>
<li>在创建Symbol值的时候可以传入一个描述description<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Symbol函数不需要new关键字来调用</span></span><br><span class="line"><span class="keyword">const</span> sym = <span class="built_in">Symbol</span>(<span class="string">&#x27;nihao&#x27;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(sym.description); <span class="comment">// nihao</span></span><br></pre></td></tr></table></figure></li>
<li>Symbol作为key的常用写法<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> s1 = <span class="built_in">Symbol</span>();</span><br><span class="line"><span class="comment">// 写法一,定义对象字面量时</span></span><br><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  [s1]: <span class="string">&#x27;Wbw~&#x27;</span>,</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 写法二, 新增属性</span></span><br><span class="line">obj[s1] = <span class="string">&#x27;Wbw~&#x27;</span>;</span><br><span class="line"><span class="comment">// 写法三,Object.defineProperty</span></span><br><span class="line"><span class="built_in">Object</span>.defineProperty(obj, s1, &#123;</span><br><span class="line">  enumerable: <span class="literal">true</span>,</span><br><span class="line">  writable: <span class="literal">true</span>,</span><br><span class="line">  configurable: <span class="literal">true</span>,</span><br><span class="line">  value: <span class="string">&#x27;Wbw~&#x27;</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(obj[s1]); <span class="comment">// Wbw~</span></span><br></pre></td></tr></table></figure></li>
<li>使用Symbol作为key的属性名,在<code>遍历/Object.keys</code>是获取不到Symbol值的,需要通过<code>Obect.getOwnPropertySymbols()方法</code>来获取所有Symbol</li>
</ul>
<ol start="11">
<li>Set的基本使用</li>
</ol>
<ul>
<li>Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是<code>元素不能重复</code>。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 数组的去重一</span></span><br><span class="line"><span class="keyword">const</span> arr = [<span class="number">11</span>, <span class="number">22</span>, <span class="number">33</span>, <span class="number">123</span>, <span class="number">11</span>];</span><br><span class="line"><span class="keyword">const</span> newArr = [];</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i <span class="keyword">of</span> arr) &#123;</span><br><span class="line">  <span class="keyword">if</span> (newArr.indexOf(i) === -<span class="number">1</span>) &#123;</span><br><span class="line">    newArr.push(i);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(newArr); <span class="comment">// [11, 22, 33, 123]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 数组的去重二</span></span><br><span class="line"><span class="keyword">const</span> arr = [<span class="number">11</span>, <span class="number">22</span>, <span class="number">33</span>, <span class="number">123</span>, <span class="number">11</span>];</span><br><span class="line"><span class="comment">// const newArr = [...new Set(arr)];</span></span><br><span class="line"><span class="keyword">const</span> newArr = <span class="built_in">Array</span>.from(<span class="keyword">new</span> <span class="built_in">Set</span>(arr));</span><br></pre></td></tr></table></figure></li>
<li>Set的属性和方法<ul>
<li><code>size</code>: 返回Set中元素的个数;</li>
<li><code>add(value)</code>: 添加某个元素,返回Set对象本身;</li>
<li><code>has(value)</code>: 判断set中是否存在某个元素,返回Boolean值;</li>
<li><code>delete(value)</code>: 从set中删除这个值相等的元素,返回Boolean值;</li>
<li><code>clear()</code>: 清空set中所有元素,无返回值;</li>
</ul>
</li>
<li>可以通过forEach或者for…of进行遍历Set</li>
</ul>
<ol start="12">
<li>WeakSet的基本使用</li>
</ol>
<ul>
<li>Set和WeakSet的区别?<ul>
<li>区别一: <code>WeakSet中只能存放对象类型</code>,不能存放基本数据类型;</li>
<li>区别二: <code>WeakSet对元素的引用是弱引用</code>,如果没有其它引用对某个对象进行引用时,GC会对该对象进行回收处理;</li>
</ul>
</li>
<li>注意点: <strong>WeakSet不能进行遍历！</strong><ul>
<li>因为WeakSet只是对对象的弱引用,如果遍历获取到其中的元素,可能会造成对象不能正常的销毁</li>
<li><strong>存储WeakSet中的对象是无法获取的</strong>;</li>
</ul>
</li>
</ul>
<ol start="13">
<li>Map的常用方法</li>
</ol>
<ul>
<li>Map类型以键值对的形式存在;</li>
<li>Map常用的属性:<ul>
<li>size: 返回Map中的元素个数;</li>
</ul>
</li>
<li>Map常用的方法:<ul>
<li><code>set(key, value)</code>: 在Map中添加key、value,并返回整个Map对象;</li>
<li><code>get(key)</code>: 根据key获取Map中的value;</li>
<li><code>has(key)</code>: 判断是否包括某个key,返回Boolean类型;</li>
<li><code>delete(key)</code>: 根据key删除一个键值对,返回Boolean类型;</li>
<li><code>clear()</code>: 删除所有的元素;</li>
</ul>
</li>
<li>可以通过forEach或者for…of进行遍历Map;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123; <span class="attr">name</span>: <span class="string">&#x27;wbw&#x27;</span> &#125;;</span><br><span class="line"><span class="comment">// 往Map中添加元素的两种方法</span></span><br><span class="line"><span class="keyword">const</span> map = <span class="keyword">new</span> <span class="built_in">Map</span>([</span><br><span class="line">  [ obj, <span class="string">&#x27;good&#x27;</span> ]</span><br><span class="line">]);</span><br><span class="line">map.set(<span class="string">&#x27;good&#x27;</span>, <span class="string">&#x27;man&#x27;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(map); <span class="comment">// Map(2) &#123;&#123; name: &#x27;wbw&#x27; &#125; =&gt; &#x27;good&#x27;, &#x27;good&#x27; =&gt; &#x27;man&#x27;&#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="14">
<li>WeakMap的使用</li>
</ol>
<ul>
<li>WeakMap和Map的区别?<ul>
<li>区别一: <strong>WeakMap的key只能使用对象</strong>,不接受其他的类型作为key;</li>
<li>区别二: WeakMap的key对对象的引用是<code>弱引用</code>,如果没有引用该对象,GC可以回收该对象。</li>
</ul>
</li>
<li>WeakMap没有size属性,打印结果为undefined;WeakMap不能进行遍历;</li>
</ul>
<ol start="15">
<li>indexOf和includes的区别</li>
</ol>
<ul>
<li><code>indexOf()</code>和<code>includes()</code>都是判断字符串或数组中是否有传入的值。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="string">&#x27;wbw&#x27;</span>, <span class="string">&#x27;lxd&#x27;</span>, <span class="string">&#x27;kiko&#x27;</span>];</span><br><span class="line"><span class="keyword">if</span> (arr.indexOf(<span class="string">&#x27;wbw&#x27;</span>) !== -<span class="number">1</span>) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;包含wbw元素&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (arr.includes(<span class="string">&#x27;wbw&#x27;</span>)) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;包含wbw元素&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><code>indexOf()</code>方法无法正确判断数组中是否有NaN,但是<code>includes()</code>方法可以判断NaN是否存在。</li>
</ul>
<h2 id="ES8知识点"><a href="#ES8知识点" class="headerlink" title="ES8知识点"></a>ES8知识点</h2><ol>
<li><p><code>Object.keys()</code>: 获取对象中所有的键。</p>
</li>
<li><p><code>Object.values()</code>: 获取对象中所有的值。</p>
</li>
<li><p><code>Object.entries()</code>: 获取对象中所有的键值对,并以数组的形式返回。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">Object</span>,keys(obj); <span class="comment">// [&#x27;name&#x27;, &#x27;age&#x27;]</span></span><br><span class="line"><span class="built_in">Object</span>.values(obj); <span class="comment">// [&#x27;wbw&#x27;, 18]</span></span><br><span class="line"><span class="comment">// 如果传入字符串,会把字符串拆分成单独的每一个,并存入数组中</span></span><br><span class="line"><span class="built_in">Object</span>.values(<span class="string">&#x27;wbw&#x27;</span>); <span class="comment">// [&#x27;w&#x27;, &#x27;b&#x27;, &#x27;w&#x27;]</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.entries(obj); <span class="comment">// [ [&#x27;name&#x27;, &#x27;wbw&#x27;], [&#x27;age&#x27;, 18] ]</span></span><br></pre></td></tr></table></figure>
<h2 id="ES10知识点"><a href="#ES10知识点" class="headerlink" title="ES10知识点"></a>ES10知识点</h2></li>
<li><p><code>flat()</code>方法会按照一个可指定深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新的数组返回。</p>
</li>
<li><p><code>flatMap()</code>方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。</p>
</li>
</ol>
<ul>
<li>注意一: flatMap是先进行map操作,再flat;</li>
<li>注意二: flatMap中的flat相当于深度为1;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> nums = [ [ [<span class="number">0</span>, <span class="number">5</span>], [<span class="number">3</span>, <span class="number">6</span>] ], <span class="number">12</span>, <span class="number">34</span>, [<span class="number">8</span>, <span class="number">99</span>], <span class="number">15</span> ];</span><br><span class="line">nums.flat(<span class="number">1</span>); <span class="comment">// [ [0, 5], [3, 6], 12, 34, 8, 99, 15 ]</span></span><br><span class="line">nums.flat(<span class="number">2</span>); <span class="comment">// [0, 5, 3, 6, 12, 34, 8, 99, 15]</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="3">
<li><code>Object.fromEntries(iterable)</code>方法将键值对列表转换为对象。</li>
</ol>
<h2 id="ES11知识点"><a href="#ES11知识点" class="headerlink" title="ES11知识点"></a>ES11知识点</h2><ol>
<li>BigInt</li>
</ol>
<ul>
<li>大于MAX_SAFE_INTEGER的数值,表示的可能是不正确的。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> maxInt = <span class="built_in">Number</span>.MAX_SAFE_INTEGER;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(maxInt + <span class="number">1</span>); <span class="comment">// 9007199254740992</span></span><br><span class="line"><span class="built_in">console</span>.log(maxInt + <span class="number">2</span>); <span class="comment">// 9007199254740992</span></span><br></pre></td></tr></table></figure></li>
<li>ES11中,引入了新的数据类型BigInt,用于表示大的整数:<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> bigInt = <span class="number">9007199254740991n</span>;</span><br><span class="line"><span class="built_in">console</span>.log(bigInt + <span class="number">1n</span>); <span class="comment">// 9007199254740992n</span></span><br><span class="line"><span class="built_in">console</span>.log(bigInt + <span class="number">2n</span>); <span class="comment">// 9007199254740993n</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="2">
<li>空值合并运算符<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> foo = <span class="number">0</span>,</span><br><span class="line">      bar = <span class="string">&quot;&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 因为||无法判断0或&quot;&quot;,可以通过??进行判断</span></span><br><span class="line"><span class="built_in">console</span>.log(foo || <span class="string">&#x27;default&#x27;</span>); <span class="comment">// default</span></span><br><span class="line"><span class="built_in">console</span>.log(bar || <span class="string">&#x27;default&#x27;</span>); <span class="comment">// default</span></span><br><span class="line"><span class="built_in">console</span>.log(foo ?? <span class="string">&#x27;default&#x27;</span>); <span class="comment">// 0</span></span><br><span class="line"><span class="built_in">console</span>.log(bar ?? <span class="string">&#x27;default&#x27;</span>); <span class="comment">// &quot;&quot;</span></span><br></pre></td></tr></table></figure></li>
<li>可选链(OptionChaining)</li>
</ol>
<ul>
<li>主要作用是让代码在进行null或undefined判断时更加清晰和简洁:<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  girlFriend: &#123;</span><br><span class="line">    name: <span class="string">&#x27;lxd&#x27;</span>,</span><br><span class="line">    age: <span class="number">18</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 以前的写法</span></span><br><span class="line"><span class="keyword">if</span> (obj &amp;&amp; obj.girlFriend) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(obj.girlFriend.name); <span class="comment">// lxd</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// ES11可选链写法</span></span><br><span class="line"><span class="built_in">console</span>.log(obj?.girlFriend); <span class="comment">// lxd</span></span><br></pre></td></tr></table></figure>
<h2 id="Proxy-Reflect"><a href="#Proxy-Reflect" class="headerlink" title="Proxy-Reflect"></a>Proxy-Reflect</h2></li>
</ul>
<ol>
<li>监听对象的操作<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">Object</span>.keys(obj).forEach(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">let</span> value = obj[item];</span><br><span class="line">  <span class="built_in">Object</span>.defineProperty(obj, item, &#123;</span><br><span class="line">    get: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="string">`监听到<span class="subst">$&#123;item&#125;</span>被访问`</span>);</span><br><span class="line">      <span class="keyword">return</span> value;</span><br><span class="line">    &#125;,</span><br><span class="line">    set: <span class="function"><span class="keyword">function</span>(<span class="params">newValue</span>) </span>&#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="string">`监听到<span class="subst">$&#123;item&#125;</span>被设置`</span>);</span><br><span class="line">      value = newValue;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="built_in">console</span>.log(obj.name); <span class="comment">// 监听到name被访问 wbw</span></span><br><span class="line">obj.name = <span class="string">&#x27;lxd&#x27;</span>; <span class="comment">// 监听到name被设置 &#x27;lxd&#x27;</span></span><br></pre></td></tr></table></figure></li>
</ol>
<ul>
<li>缺点: 无法监听更加丰富的操作,比如<code>删除属性</code>、<code>新增属性</code>。</li>
</ul>
<ol start="2">
<li>Proxy基本使用</li>
</ol>
<ul>
<li>如果想要<code>监听一个对象的相关操作</code>,可以先<code>创建一个代理对象(Proxy对象)</code>;</li>
<li>之后对<code>该对象的所有操作</code>,都通过<code>代理对象来完成</code>,代理对象<code>可以监听我们想要对原对象进行哪些操作</code>;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 首先new Proxy对象,并传入需要侦听的对象和一个处理对象,称之为handle</span></span><br><span class="line"><span class="keyword">const</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(obj, &#123;</span><br><span class="line">  get: <span class="function"><span class="keyword">function</span>(<span class="params">target, key</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`obj中的<span class="subst">$&#123;key&#125;</span>属性被访问`</span>);</span><br><span class="line">    <span class="keyword">return</span> target[key];</span><br><span class="line">  &#125;,</span><br><span class="line">  set: <span class="function"><span class="keyword">function</span>(<span class="params">target, key, newValue</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`obj中的<span class="subst">$&#123;key&#125;</span>属性被设置`</span>);</span><br><span class="line">    target[key] = newValue;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 监听in的捕获器</span></span><br><span class="line">  has: <span class="function"><span class="keyword">function</span>(<span class="params">target, key</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`监听到obj中的<span class="subst">$&#123;key&#125;</span>属性in操作`</span>);</span><br><span class="line">    <span class="keyword">return</span> key <span class="keyword">in</span> target;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 监听delete的捕获器</span></span><br><span class="line">  deleteProperty: <span class="function"><span class="keyword">function</span>(<span class="params">target, key</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`监听到obj中的<span class="subst">$&#123;key&#125;</span>属性delete操作`</span>);</span><br><span class="line">    <span class="keyword">delete</span> target[key];</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接操作Proxy的实例对象</span></span><br><span class="line"><span class="built_in">console</span>.log(proxy.name); <span class="comment">// obj中的name被访问 &#x27;wbw&#x27;</span></span><br><span class="line">proxy.name = <span class="string">&#x27;lxd&#x27;</span>; <span class="comment">// obj中的name被设置&#x27;lxd&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// in操作符</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;name&quot;</span> <span class="keyword">in</span> proxy); <span class="comment">// 监听到obj中的name属性in操作 true</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// delete操作符</span></span><br><span class="line"><span class="keyword">delete</span> proxy.name; <span class="comment">// 监听到obj中的age属性delete操作 false</span></span><br></pre></td></tr></table></figure></li>
<li>如果要侦听某些具体的操作,可以在handler中添加对应的捕捉器(trap):</li>
<li><code>set函数</code>有四个参数:<ul>
<li>target: 目标对象(侦听的对象);</li>
<li>property: 将要被设置的属性key;</li>
<li>value: 新属性值;</li>
<li>receiver: 调用的代理对象;</li>
</ul>
</li>
<li><code>get函数</code>有三个参数:<ul>
<li>target: 目标对象(侦听的对象);</li>
<li>property: 被获取的属性key;</li>
<li>receiver: 调用的代理对象;</li>
</ul>
</li>
<li><code>has函数</code>和<code>deleteProperty函数</code>有两个参数:<ul>
<li>target: 目标对象(侦听的对象);</li>
<li>property: 被获取的属性key;</li>
</ul>
</li>
<li>其他函数方法参照MDN: <strong><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy</a></strong><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(foo, &#123;</span><br><span class="line">  <span class="comment">// 函数调用操作捕获器</span></span><br><span class="line">  apply: <span class="function"><span class="keyword">function</span>(<span class="params">target, thisArg, argArray</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;对foo函数进行了apply调用&#x27;</span>);</span><br><span class="line">    target.apply(thisArg, argArray);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// new操作符捕获器</span></span><br><span class="line">  construct: <span class="function"><span class="keyword">function</span>(<span class="params">target, argArray</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;对foo函数进行了new调用&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> target(...argArray);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line">proxy.apply(&#123;&#125;, [<span class="string">&#x27;wbw&#x27;</span>, <span class="string">&#x27;lxd&#x27;</span>]);</span><br><span class="line"><span class="keyword">new</span> proxy();</span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="3">
<li>Reflect的作用</li>
</ol>
<ul>
<li>Reflect是ES6新增的一个API,它是一个<code>对象</code>;</li>
<li>Reflect的用处?<ul>
<li>它提供了很多<strong>操作JavaScript对象的方法</strong>,和<strong>Object中操作对象的方法</strong>类似;</li>
</ul>
</li>
<li>Reflect的常见方法与Proxy一一对应,只列出重要的几个:<ul>
<li><code>Reflect.has(target, propertyKey)</code>: 判断一个对象是否存在某个属性,和in运算符的功能完全相同</li>
<li><code>Reflect.get(target, propertyKey[,receiver])</code>: 获取对象上某个属性的值,类似于<code>target[name]</code>;</li>
<li><code>Reflect.set(target, propertyKey, newValue[, receiver]</code>: 将值分配给对应属性的函数;如果更新成功则返回true;</li>
<li><code>Reflect.deleteProperty(target, propertyKey)</code>: 作为函数的delete操作符,相当于执行<code>delete target[name]</code>;</li>
</ul>
</li>
</ul>
<ol start="4">
<li>Receiver的作用</li>
</ol>
<ul>
<li><strong>如果源对象有getter、setter的访问器属性,那么可以通过receiver来改变this的指向</strong>。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  _name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  <span class="function"><span class="title">get</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">this</span>._name;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="title">set</span>(<span class="params">newValue</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>._name = newValue;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(obj, &#123;</span><br><span class="line">  <span class="comment">// 将this指向proxy代理对象</span></span><br><span class="line">  set: <span class="function"><span class="keyword">function</span>(<span class="params">target, key, newValue, receiver</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Reflect</span>.set(target, key, newValue, receiver);</span><br><span class="line">  &#125;,</span><br><span class="line">  get: <span class="function"><span class="keyword">function</span>(<span class="params">target, key, receiver</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Reflect</span>.get(target, key, receiver);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="5">
<li>Reflect的construct<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Student</span>(<span class="params">name, age</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.name = name;</span><br><span class="line">  <span class="built_in">this</span>.age = age;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Teacher</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> stu = <span class="built_in">Reflect</span>.construct(Student, [<span class="string">&#x27;wbw&#x27;</span>, <span class="number">18</span>], Teacher);</span><br><span class="line"><span class="built_in">console</span>.log(stu.__proto__ === Teacher.prototype); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<!-- ## Vue3响应式和Vue2响应式 -->

</li>
</ol>
<h2 id="Promise及手写Promise"><a href="#Promise及手写Promise" class="headerlink" title="Promise及手写Promise"></a>Promise及手写Promise</h2><blockquote>
<ol>
<li>promise: <a target="_blank" rel="noopener" href="https://784801819.github.io/2021/02/17/js-yi-bu-bian-cheng-zhi-shi-dian/#toc-heading-4">https://784801819.github.io/2021/02/17/js-yi-bu-bian-cheng-zhi-shi-dian/#toc-heading-4</a></li>
</ol>
</blockquote>
<blockquote>
<ol start="2">
<li>手写promise: <a target="_blank" rel="noopener" href="https://784801819.github.io/2021/02/19/shou-xie-promise/">https://784801819.github.io/2021/02/19/shou-xie-promise/</a></li>
</ol>
</blockquote>
<h2 id="迭代器-可迭代对象-生成器用法"><a href="#迭代器-可迭代对象-生成器用法" class="headerlink" title="迭代器-可迭代对象-生成器用法"></a>迭代器-可迭代对象-生成器用法</h2><h3 id="迭代器"><a href="#迭代器" class="headerlink" title="迭代器"></a>迭代器</h3><ol>
<li>在JavaScript中，迭代器也是一个<code>具体的对象</code>，这个对象需要符合<code>迭代器协议</code>:</li>
</ol>
<ul>
<li>在js中这个标准就是一个特定的<code>next方法</code>;</li>
</ul>
<ol start="2">
<li>next方法有如下要求:</li>
</ol>
<ul>
<li>一个无参数函数,返回一个应当拥有以下两个属性的对象:<ul>
<li><strong>done(boolean)</strong>: <code>如果迭代器可以产生序列中的下一个值,则为false。如果迭代器已将序列迭代完毕,则为true</code>。这种情况下,value是可选的,如果它依然存在,即为迭代结束的默认返回值</li>
<li>value: 迭代器返回的任何JavaScript值,done为true时可省略。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createArrayIterator</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    next: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">if</span> (index &lt; arr.length) &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">false</span>, <span class="attr">value</span>: arr[index++] &#125;;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">true</span>, <span class="attr">value</span>: <span class="literal">undefined</span> &#125;;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<ol start="3">
<li>可迭代对象</li>
</ol>
<ul>
<li>它和迭代器概念是不同的;</li>
<li>当一个对象实现了iterable protocol协议时,它就是一个可迭代对象;</li>
<li>这个对象的要求是必须实现<code>@@iterator</code>方法,在代码中使用<code>Symbol.iterator</code>访问该属性;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> iterableObj = &#123;</span><br><span class="line">  friends: [<span class="string">&#x27;wbw&#x27;</span>, <span class="string">&#x27;lxd&#x27;</span>, <span class="string">&#x27;kiko&#x27;</span>],</span><br><span class="line">  [Symbole.iterator]: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">// 返回一个迭代器</span></span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      next: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (index &lt; <span class="built_in">this</span>.friends.length) &#123;</span><br><span class="line">          <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">false</span>, <span class="attr">value</span>: <span class="built_in">this</span>.friends[index++] &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">true</span>, <span class="attr">value</span>: <span class="literal">undefined</span> &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">const</span> item <span class="keyword">of</span> ierableObj) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(item); <span class="comment">// wbw lxd kiko</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="4">
<li>原生迭代器对象</li>
</ol>
<ul>
<li>String、Array、Map、Set、arguments对象、NodeList集合(DOM);</li>
</ul>
<ol start="5">
<li>可迭代对象的应用</li>
</ol>
<ul>
<li>JavaScript中的语法: for…of、展开运算符、yield*、解构赋值;</li>
<li>创建一些对象时: new Map([Iterable])、new WeakMap([Iterable])、new Set([Iterable])、new WeakSet([Iterable]);</li>
<li>一些方法的调用: Promise.all(iterable)、Promise.race(iterable)、Array.from(iterable);</li>
</ul>
<ol start="6">
<li>自定义类的迭代</li>
</ol>
<ul>
<li>面向对象开发中,可以通过class定义一个自己的类,这个类可以创建很多对象。</li>
<li>如果希望自己的类创建出来的对象默认是可迭代的,可以在类里添加@@iterator方法;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Classroom</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">name, address, students</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.name = name;</span><br><span class="line">    <span class="built_in">this</span>.address = address;</span><br><span class="line">    <span class="built_in">this</span>.students = students;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="title">entry</span>(<span class="params">student</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.students.push(student);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 这里是关键</span></span><br><span class="line">  [<span class="built_in">Symbol</span>.iterator]() &#123;</span><br><span class="line">    <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      next: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (index &lt; <span class="built_in">this</span>.students.length) &#123;</span><br><span class="line">          <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">false</span>, <span class="attr">value</span>: <span class="built_in">this</span>.students[index++] &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">true</span>, <span class="attr">value</span>: <span class="literal">undefined</span> &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="comment">// 终止迭代器</span></span><br><span class="line">      <span class="keyword">return</span>: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;迭代器终止&#x27;</span>);</span><br><span class="line">        <span class="comment">// 终止需返回一个done为true的对象</span></span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">true</span> &#125;;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> classroom = <span class="keyword">new</span> Classroom(<span class="string">&#x27;111&#x27;</span>, <span class="string">&#x27;222&#x27;</span>, [<span class="string">&#x27;wbw&#x27;</span>, <span class="string">&#x27;lxd&#x27;</span>]);</span><br><span class="line">classroom.entry(<span class="string">&#x27;kiko&#x27;</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> item <span class="keyword">of</span> classroom) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(item); <span class="comment">// wbw lxd kiko</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="生成器"><a href="#生成器" class="headerlink" title="生成器"></a>生成器</h3></li>
</ul>
<ol>
<li>什么是生成器?</li>
</ol>
<ul>
<li>生成器是ES6中新增的一种函数控制、使用的方案,可以灵活控制函数什么时候开始执行、结束执行等。</li>
<li>生成器函数也是一个函数,和普通函数的区别:<ul>
<li><strong>生成器函数需要在function后面加一个符号: <code>*</code></strong>;</li>
<li><strong>生成器函数可以通过yield关键字来控制函数的执行流程</strong></li>
<li><strong>生成器函数的返回值是一个Generator(生成器),是一个特殊的迭代器</strong><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 遇到yield时暂停函数的执行</span></span><br><span class="line"><span class="comment">// 遇到return时生成器停止执行</span></span><br><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">generator</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;函数执行开始&quot;</span>);</span><br><span class="line">  <span class="keyword">yield</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> value1 = <span class="number">100</span>;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;第一段代码:&quot;</span>, value1);</span><br><span class="line">  <span class="comment">// 如果不希望next返回的是undefined时,在yield后跟需要返回的值即可</span></span><br><span class="line">  <span class="keyword">yield</span> value1</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> value2 = <span class="number">200</span>;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;第二段代码:&quot;</span>, value2);</span><br><span class="line">  <span class="keyword">yield</span> value2</span><br><span class="line"></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;函数执行结束&quot;</span>);</span><br><span class="line">  <span class="keyword">return</span> <span class="string">&quot;www&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> generator1 = generator();</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(generator1.next()) <span class="comment">// 函数执行开始, &#123; done: false, value: undefined &#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator1.next()); <span class="comment">// 第一段代码: 100 &#123;value: 100, done: false&#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator1.next()); <span class="comment">// 第二段代码: 200 &#123;value: 200, done: false&#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator1.next()); <span class="comment">// 函数执行结束 &#123; value: &quot;www&quot;, done: true &#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<ol start="2">
<li>生成器传递参数-next函数</li>
</ol>
<ul>
<li><strong>在调用next函数的时候,可以给他传递参数,那么这个参数会作为上一个yield语句的返回值</strong></li>
<li>也就是说我们为本次的函数代码块执行提供了一个值;<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">foo</span>(<span class="params">i</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> value1 = <span class="keyword">yield</span> i + <span class="string">&#x27;aaa&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> value2 = <span class="keyword">yield</span> value1 + <span class="string">&#x27;bbb&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> value3 = <span class="keyword">yield</span> value2 + <span class="string">&#x27;ccc&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> generator = foo(<span class="string">&#x27;wbw&#x27;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(generator.next()); <span class="comment">// &#123; done: false, value: wbwaaa &#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator.next(<span class="string">&#x27;lxd&#x27;</span>)); <span class="comment">// &#123; done: false, value: lxdbbb &#125;;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator.next(<span class="string">&#x27;kiko&#x27;</span>)); <span class="comment">// &#123; done: false, value: kikoccc &#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator.next()); <span class="comment">// &#123; done: true &#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<ol start="3">
<li>生成器代替迭代器<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">createArrayIterator</span>(<span class="params">arr</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 写法一</span></span><br><span class="line">  <span class="keyword">for</span>(<span class="keyword">const</span> item <span class="keyword">of</span> arr) &#123;</span><br><span class="line">    <span class="keyword">yield</span> item;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 写法二: yield* + 可迭代对象（语法糖）</span></span><br><span class="line">  <span class="keyword">yield</span>* arr</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> names = [<span class="string">&#x27;wbw&#x27;</span>, <span class="string">&#x27;lxd&#x27;</span>, <span class="string">&#x27;kiko&#x27;</span>];</span><br><span class="line"><span class="keyword">const</span> generator = createArrayIterator(names);</span><br><span class="line"><span class="built_in">console</span>.log(generator.next()); <span class="comment">// &#123; done: false, value: &#x27;wbw&#x27; &#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator.next()); <span class="comment">// &#123; done: false, value: &#x27;lxd&#x27; &#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator.next()); <span class="comment">// &#123; done: false, value: &#x27;kiko&#x27; &#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(generator.next()); <span class="comment">// &#123; done: true &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 既然生成器是一个迭代器,可以对其进行如下的操作</span></span><br><span class="line"><span class="keyword">const</span> names1 = createArrayIterator(names);</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">const</span> item <span class="keyword">of</span> names1) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(item);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> names2 = createArrayIterator(names);</span><br><span class="line"><span class="keyword">const</span> set = <span class="keyword">new</span> <span class="built_in">Set</span>(names2);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> names3 = createArrayIterator(names);</span><br><span class="line"><span class="built_in">Promise</span>.all(names3).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(res);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<h2 id="异步代码的处理方式"><a href="#异步代码的处理方式" class="headerlink" title="异步代码的处理方式"></a>异步代码的处理方式</h2></li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">requestData</span>(<span class="params">url</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">      resolve(url);</span><br><span class="line">    &#125;, <span class="number">2000</span>);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 第一种方法: 回调处理,该方法会产生回调地狱,代码的阅读性非常差</span></span><br><span class="line">requestData(<span class="string">&#x27;wbw&#x27;</span>).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">  requestData(<span class="string">`<span class="subst">$&#123;res&#125;</span>lxd`</span>).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    requesData(<span class="string">`<span class="subst">$&#123;res&#125;</span>kiko`</span>).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="built_in">console</span>.log(res);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 第二种方法: Promise中then的返回值,该方法阅读性也不好</span></span><br><span class="line">requestData(<span class="string">&#x27;wbw&#x27;</span>).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> requestData(<span class="string">`<span class="subst">$&#123;res&#125;</span>lxd`</span>);</span><br><span class="line">&#125;).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> requestData(<span class="string">`<span class="subst">$&#123;res&#125;</span>kiko`</span>);</span><br><span class="line">&#125;).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(res);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 第三种方法: Promise + generator</span></span><br><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">getData</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> res1 = <span class="keyword">yield</span> requestData(<span class="string">&#x27;wbw&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> res2 = <span class="keyword">yield</span> requestData(<span class="string">`<span class="subst">$&#123;res1&#125;</span>lxd`</span>);</span><br><span class="line">  <span class="keyword">const</span> res3 = <span class="keyword">yield</span> requestData(<span class="string">`<span class="subst">$&#123;res2&#125;</span>kiko`</span>);</span><br><span class="line">  <span class="built_in">console</span>.log(res3);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 1. 手动调用</span></span><br><span class="line"><span class="keyword">const</span> generator = getData();</span><br><span class="line">generator.next().value.then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">  generator.next(res).value.then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    generator.next(res).value.then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">      generator.next(res); <span class="comment">// wbwlxdkiko</span></span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2. 第三方库 co自动执行</span></span><br><span class="line"><span class="comment">// 先要npm install co将包下载</span></span><br><span class="line"><span class="keyword">const</span> co = <span class="built_in">require</span>(<span class="string">&#x27;co&#x27;</span>);</span><br><span class="line">co(getData); <span class="comment">// wbwlxdkiko</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3. 终极方案 async/await(generator的语法糖)</span></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">getData</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> res1 = <span class="keyword">await</span> requestData(<span class="string">&#x27;wbw&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> res2 = <span class="keyword">await</span> requestData(<span class="string">`<span class="subst">$&#123;res1&#125;</span>lxd`</span>);</span><br><span class="line">  <span class="keyword">const</span> res3 = <span class="keyword">await</span> requestData(<span class="string">`<span class="subst">$&#123;res2&#125;</span>kiko`</span>);</span><br><span class="line">  <span class="built_in">console</span>.log(res3);</span><br><span class="line">&#125;</span><br><span class="line">getData(); <span class="comment">// wbwlxdkiko</span></span><br></pre></td></tr></table></figure>
<h2 id="异步函数async-await用法"><a href="#异步函数async-await用法" class="headerlink" title="异步函数async/await用法"></a>异步函数async/await用法</h2><blockquote>
<p><a target="_blank" rel="noopener" href="https://784801819.github.io/2021/02/17/js-yi-bu-bian-cheng-zhi-shi-dian/">https://784801819.github.io/2021/02/17/js-yi-bu-bian-cheng-zhi-shi-dian/</a></p>
</blockquote>
<h2 id="Event-Loop-事件循环"><a href="#Event-Loop-事件循环" class="headerlink" title="Event Loop(事件循环)"></a>Event Loop(事件循环)</h2><blockquote>
<p><a target="_blank" rel="noopener" href="https://784801819.github.io/2021/02/19/event-loop/#toc-heading-4">https://784801819.github.io/2021/02/19/event-loop/#toc-heading-4</a></p>
</blockquote>
<ol>
<li>面试题1<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;setTimeout1&quot;</span>);</span><br><span class="line">  <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">    resolve();</span><br><span class="line">  &#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">      resolve();</span><br><span class="line">    &#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="string">&quot;then4&quot;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;then2&quot;</span>);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;promise1&quot;</span>);</span><br><span class="line">  resolve();</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;then1&quot;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;setTimeout2&quot;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">queueMicrotask(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;queueMicrotask1&quot;</span>)</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">  resolve();</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&quot;then3&quot;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// promise1 ==&gt; 2 ==&gt; then1 ==&gt; queueMicrotask1 ==&gt; then3 ==&gt; setTimeout1 ==&gt; then2 ==&gt; then4 ==&gt; setTimeout2</span></span><br></pre></td></tr></table></figure></li>
</ol>
<ul>
<li>分析: 从上至下,首先setTimeout整个会被放到宏任务队列中,往下执行,new Promise会立即执行,promise1会被打印,then1会被放入微任务队列中;随后setTimeout会被放入到宏任务队列中,固第二个打印的必然是2,继续往下执行,queueMicrotask因为是微任务,所以会被放到微任务队列中,最后then3同理,也会被放入到微任务队列中。因为宏任务执行之前,会先清空微任务队列,所以依次打印then1、queueMicrotask、then3;开始执行宏任务队列,setTimeout1会被打印,随后then2、then4依次会被放入到微任务队列中。宏任务执行前清空微任务队列,依次打印then2、then4、setTimeout2</li>
</ul>
<ol start="2">
<li>面试题二:<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;script start&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">await</span> async2()</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;async1 end&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;async2 end&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line">async1()</span><br><span class="line"></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;setTimeout&#x27;</span>)</span><br><span class="line">&#125;, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;Promise&#x27;</span>)</span><br><span class="line">  resolve()</span><br><span class="line">&#125;)</span><br><span class="line">  .then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise1&#x27;</span>)</span><br><span class="line">  &#125;)</span><br><span class="line">  .then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;promise2&#x27;</span>)</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;script end&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// script start -&gt; async2 end -&gt; Promise -&gt; script end -&gt; async1 end -&gt; promise1 -&gt; promise2 -&gt; setTimeout</span></span><br></pre></td></tr></table></figure></li>
</ol>
<ul>
<li>分析: 从上至下, 因为script start为script代码,必然会立刻执行;继续往下执行,发现async1被调用,async1函数中又调用了async2,所以第二个打印的必然是async2 end;async2执行完毕后,因为函数执行完如果没返回值默认return undefined;等同于resolve(undefined),所以async1 end会被放入微任务队列中;继续执行发现setTimeout,setTimeout会被放入到宏任务队列;new Promise()时,会立即调用,故会打印Promise、且promise1和promise2会被放入微任务队列等待打印;往下发现script end;最后会将微任务队列中所有任务执行完后,最后才会输出宏任务中的setTimeout;</li>
</ul>
<ol start="3">
<li>面试题三(node)<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;async1 start&#x27;</span>)</span><br><span class="line">  <span class="keyword">await</span> async2()</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;async1 end&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">async2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;async2&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;script start&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;setTimeout0&#x27;</span>)</span><br><span class="line">&#125;, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;setTimeout2&#x27;</span>)</span><br><span class="line">&#125;, <span class="number">300</span>)</span><br><span class="line"></span><br><span class="line">setImmediate(<span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="string">&#x27;setImmediate&#x27;</span>));</span><br><span class="line"></span><br><span class="line">process.nextTick(<span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="string">&#x27;nextTick1&#x27;</span>));</span><br><span class="line"></span><br><span class="line">async1();</span><br><span class="line"></span><br><span class="line">process.nextTick(<span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="string">&#x27;nextTick2&#x27;</span>));</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;promise1&#x27;</span>)</span><br><span class="line">  resolve();</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;promise2&#x27;</span>)</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;promise3&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;script end&#x27;</span>)</span><br><span class="line"><span class="comment">// script start ==&gt; async1 start ==&gt; async2 ==&gt; promise1 ==&gt; promise2 ==&gt; script end ==&gt; nextTick1 ==&gt; nextTick2 ==&gt; async1 end ==&gt; promise3 ==&gt; setTimeout0 ==&gt; setImmediate ==&gt; setTimeout2</span></span><br></pre></td></tr></table></figure></li>
</ol>
<ul>
<li>分析: 代码从上往下依次执行,因为async1、async2函数未被调用,代码继续向下执行,第一个打印的必然是script start;继续向下执行,setTimeout0和setTimeout2依次被放入宏任务队列中;setImmediate会放入check中等待调用;继续向下执行,nextTick1被放入到nextTick队列中;开始执行async1,第二个打印的是async1 start,随后async2被调用,第三个打印的是async2,async1 end会被放入到微任务队列中;随后new Promise立即执行,第四个打印的是promise1,promise2被放入微任务队列中,第五个打印promise2,第六个打印script end;nextTick队列永远会在mircotask之前执行,因为nextTick是独立于event loop之外的,所以会优先执行,所以nextTick1、nextTick2被打印;随后开始执行微任务队列,依次打印async1 end、promise3,微任务队列执行完毕,开始执行红任务队列,打印setTimeout0,因为setTimeout2延迟300ms,所以先打印setImmediate,最后才会打印setTimeout2</li>
</ul>
<h2 id="异常处理-CommonJS模块化"><a href="#异常处理-CommonJS模块化" class="headerlink" title="异常处理-CommonJS模块化"></a>异常处理-CommonJS模块化</h2><ol>
<li><p>异常的捕获(try…catch)</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">  <span class="comment">// try statements</span></span><br><span class="line">&#125; <span class="keyword">catch</span>(err) &#123;</span><br><span class="line">  <span class="comment">// catch statements</span></span><br><span class="line">&#125; [<span class="keyword">finally</span> &#123;</span><br><span class="line">  <span class="comment">// finally statements</span></span><br><span class="line">&#125;]</span><br></pre></td></tr></table></figure>
<ul>
<li>如果有必须要执行的代码,可以使用finally来执行,它类似于promise中的finally</li>
<li>finally表示最终一定会被执行的代码结构</li>
<li>注意: 如果try和finally都有返回值,那么会使用finally的返回值</li>
</ul>
</li>
<li><p>什么是模块化开发?</p>
<ul>
<li>模块化开发最终目的是将程序划分成一个个小的结构;</li>
<li>每个结构中编写属于<code>自己的逻辑代码</code>,有<code>自己的作用域</code>,<code>互不干扰</code>;</li>
<li>这个结构可以将自己希望暴露的变量、函数、对象等导出给其他结构使用。</li>
<li>也可以通过某种方式,导入另外结构中的变量、函数、对象等;</li>
</ul>
</li>
<li><p>CommonJS</p>
</li>
</ol>
<ul>
<li><strong>exports是一个对象,可以在这个对象中添加很多属性,这些添加的属性会被导出</strong><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 一个文件中导出</span></span><br><span class="line"><span class="built_in">exports</span>.name = name;</span><br><span class="line"><span class="built_in">exports</span>.age = age;</span><br><span class="line"><span class="comment">// 另一个文件中导入</span></span><br><span class="line"><span class="keyword">const</span> obj = <span class="built_in">require</span>(<span class="string">&#x27;./index&#x27;</span>);</span><br></pre></td></tr></table></figure></li>
<li>上面这行完成的操作如下:<ul>
<li>require通过各种查找方式,找到了exports对象;</li>
<li>将exports对象赋值给了obj变量;</li>
<li><strong>所以,exports对象等于obj变量</strong></li>
</ul>
</li>
<li>module.exports和exports有什么关系和区别?<ul>
<li>在Node中真正导出的是<code>module.exports</code>,并非<code>exports</code>;</li>
</ul>
</li>
<li>为什么exports可以导出呢?<ul>
<li>因为module对象的exports属性是exports对象的一个引用</li>
<li>也就是：<code>module.exports = exports = obj</code>,三者都是引用的同一个地址,相互影响</li>
</ul>
</li>
<li>require细节<ol>
<li>导入格式为: require(X)</li>
<li>情况一: X是一个Node核心模块,比如path、http<ul>
<li>直接返回核心模块,并且停止查找</li>
</ul>
</li>
<li><strong>情况二</strong>: X是以<code>./</code>或<code>../</code>或<code>/(根目录)</code>开头的<ul>
<li>如果有后缀名,按照后缀名的格式查找对于的文件</li>
<li><strong>如果没有后缀名: 先查找文件X、如果没有开始查找X.js文件、如果还没有查找到继续查找X.json文件,最后会查找X.node文件</strong></li>
<li><strong>没有找到对于的文件时,将X作为一个目录。查找目录下的index文件,依次查找index.js、index.json和index.node文件;如果最后没找到,报错not found</strong></li>
</ul>
</li>
<li>情况三: X不是核心模块也不是路径<ul>
<li>会在node_modules文件下查找,一般用于引入第三方库</li>
</ul>
</li>
</ol>
</li>
<li>模块加载过程<ol>
<li>结论一: 模块在被第一次引入时,模块中的js代码会被运行一次</li>
<li>结论二: 模块被引入多次时,会有缓存,最终只会加载一次(内部会通过一个loaded属性进行控制是否被加载过)</li>
</ol>
</li>
</ul>
<h2 id="ESModule模块化"><a href="#ESModule模块化" class="headerlink" title="ESModule模块化"></a>ESModule模块化</h2><ol>
<li><p>导出的两种方式(export)</p>
 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 方式一: export声明语句</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;wbw&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> age = <span class="number">23</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;foo导出了&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">Wang</span> </span>&#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 方式二: export导出和声明分开</span></span><br><span class="line"><span class="keyword">const</span> name = <span class="string">&#x27;wbw&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> age = <span class="number">23</span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;foo导出了&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 这里不是ES6的对象字面量增强写法, &#123;&#125;也不是表示为一个对象</span></span><br><span class="line"><span class="keyword">export</span> &#123;</span><br><span class="line">  name,</span><br><span class="line">  age,</span><br><span class="line">  foo</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>导入的三种方式(import)</p>
 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 方式一: 普通的导入</span></span><br><span class="line"><span class="keyword">import</span> &#123; name, age, foo &#125; <span class="keyword">from</span> <span class="string">&#x27;模块&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 方式二: 起别名</span></span><br><span class="line"><span class="keyword">import</span> &#123; name <span class="keyword">as</span> wName, age <span class="keyword">as</span> wAge, foo <span class="keyword">as</span> Foo &#125; <span class="keyword">from</span> <span class="string">&#x27;模块&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 方式三: 将导出的所有内容放到一个标识符中</span></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> otherName <span class="keyword">from</span> <span class="string">&#x27;模块&#x27;</span>;</span><br></pre></td></tr></table></figure></li>
<li><p>default用法</p>
<ul>
<li>默认导出export时可以不需要指定名字;</li>
<li>导入的时候不需要使用{},并且可以自定义名字;</li>
<li>注意: <strong>在一个模块中,只能有一个默认导出(default export)</strong><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 默认导出一: 命名默认导出</span></span><br><span class="line"><span class="keyword">export</span> &#123;</span><br><span class="line">  name <span class="keyword">as</span> <span class="keyword">default</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 默认导出二: 常见默认导出</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> name;</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>export和import结合使用</p>
<ul>
<li>在开发和封装一个功能库时,一般希望将暴露的所有接口放在一个文件里。方便指定统一接口规范,方便阅读<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> &#123; sum <span class="keyword">as</span> Wsum &#125; <span class="keyword">from</span> <span class="string">&#x27;模块&#x27;</span>;</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>import函数</p>
<ul>
<li>通过import加载一个模块,是不可以放到逻辑代码中</li>
<li>这是因为这个时候js代码不会被运行</li>
<li>如果希望动态加载某一个模块,可以使用import()函数进行动态加载<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">  <span class="keyword">import</span>(<span class="string">&#x27;./modules/a.js&#x27;</span>).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(res);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="keyword">import</span>(<span class="string">&#x27;./modules/b.js&#x27;</span>).then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(res);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>ESModule的解析流程<br><a target="_blank" rel="noopener" href="https://imgtu.com/i/LnXwN9"><img src="https://s1.ax1x.com/2022/04/12/LnXwN9.png" alt="LnXwN9.png"></a></p>
<ul>
<li>阶段一:构建(construction),根据地址查找js文件,并且下载,将其解析成<code>模块记录</code>(module record)<br><a target="_blank" rel="noopener" href="https://imgtu.com/i/LnxbDK"><img src="https://s1.ax1x.com/2022/04/12/LnxbDK.png" alt="LnxbDK.png"></a></li>
<li>阶段二:实例化(instantiation),对模块记录进行实例化,并且分配内存空间,解析模块的导入导出语句,把模块指向对应的内存地址</li>
<li>阶段三:运行代码,计算值,并且将值填充到内存地址中<br><a target="_blank" rel="noopener" href="https://imgtu.com/i/LupwND"><img src="https://s1.ax1x.com/2022/04/12/LupwND.png" alt="LupwND.png"></a></li>
</ul>
</li>
</ol>
<h2 id="包管理工具"><a href="#包管理工具" class="headerlink" title="包管理工具"></a>包管理工具</h2><ol>
<li>常见的属性<ul>
<li>必填的属性: name、version<ul>
<li>name为项目的名称</li>
<li>version为当前项目的版本号</li>
<li>description是描述信息</li>
<li>author是作者相关信息(发布时用到)</li>
<li>license是开源协议(发布时用到)</li>
</ul>
</li>
<li>private属性:<ul>
<li>记录当前项目是否为私有的</li>
<li>当为true的时候,npm是不能发布的,防止私有项目或模块被发布出去</li>
</ul>
</li>
<li>scripts属性:<ul>
<li>用于配置一些脚本命令,以键值对的形式存在</li>
<li>配置后通过npm run 命令的key来执行这个命令</li>
</ul>
</li>
<li>dependencies属性:<ul>
<li>dependencies属性是指定无论是开发环境还是生产环境都需要依赖的包</li>
</ul>
</li>
<li>devDependencies属性:<ul>
<li>一些包在生产环境是不需要的,比如webpack、Babel等</li>
<li>通过<code>npm install package --save-dev</code>,将其安装到devDependencies中</li>
</ul>
</li>
<li>peerDependencies属性:<ul>
<li>对等依赖,也就是你依赖的一个包,必须是以另外一个宿主包为前提的</li>
</ul>
</li>
</ul>
</li>
<li>依赖的版本管理<ul>
<li>^和~的区别:<ul>
<li>^x.y.z:表示x是保持不变的,y和z永远安装最新的版本</li>
<li>~x.y.z:表示x和y保持不变,z永远安装最新的版本</li>
<li>x和y分别表示主版本号和次版本号,z表示的是修订号</li>
</ul>
</li>
</ul>
</li>
<li>npm install命令<ul>
<li>安装npm包分两种情况:<ul>
<li>全局安装(global install): <code>npm install package -g</code></li>
<li>项目安装(local install): <code>npm install package</code></li>
</ul>
</li>
</ul>
</li>
<li>卸载某个依赖包: <code>npm uninstall package</code></li>
<li>发布自己的包<ul>
<li>在npm注册自己的账号,并在命令行中执行<code>npm login</code></li>
<li>修改package.json</li>
<li>执行<code>npm publish</code>发布到npm仓库中</li>
<li>更新仓库:<ul>
<li>修改版本号(符合semver规范)</li>
<li>npm publish</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="深拷贝"><a href="#深拷贝" class="headerlink" title="深拷贝"></a>深拷贝</h2><ol>
<li>使用JSON序列化深拷贝<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  name: <span class="string">&#x27;wbw&#x27;</span>,</span><br><span class="line">  age: <span class="number">18</span>,</span><br><span class="line">  friends: &#123;</span><br><span class="line">   name: <span class="string">&#x27;lxd&#x27;</span>,</span><br><span class="line">   age: <span class="number">18</span></span><br><span class="line">  &#125;,</span><br><span class="line">  foo: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;hello world&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> objString = <span class="built_in">JSON</span>.stringify(obj);</span><br><span class="line"><span class="keyword">const</span> info = <span class="built_in">JSON</span>.parse(objString);</span><br><span class="line"><span class="built_in">console</span>.log(info); <span class="comment">// &#123; &quot;name&quot;: &quot;wbw&quot;, &quot;age&quot;: 18, &quot;friends&quot;: &#123; &quot;name&quot;: &quot;lxd&quot;, &quot;age&quot;: 18 &#125;&#125;</span></span><br><span class="line"><span class="comment">// 这里改变了info中friends对象的name属性</span></span><br><span class="line">info.friends.name = <span class="string">&#x27;kiko&#x27;</span>;</span><br><span class="line"><span class="comment">// 可以看出obj中的friends并没有受到影响</span></span><br><span class="line"><span class="built_in">console</span>.log(obj.friends.name); <span class="comment">// lxd</span></span><br></pre></td></tr></table></figure>
<ul>
<li>注意: 从上述代码可以看出,foo这个函数不见了,所以JSON实现深拷贝的方法是有缺陷的。<strong>会忽略undefined</strong>、<strong>会忽略symbol</strong>、不<strong>能序列化函数</strong>以及<strong>如果存在对象的循环引用也会报错</strong></li>
</ul>
</li>
</ol>

                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/wangbowen-hexo-blog/about" rel="external nofollow noreferrer">W.BOWEN</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://gitee.com/wang-bowen0629/wangbowen-hexo-blog/2021/11/03/js-zhi-shi-dian-zong-jie-chi-xu-geng-xin/">https://gitee.com/wang-bowen0629/wangbowen-hexo-blog/2021/11/03/js-zhi-shi-dian-zong-jie-chi-xu-geng-xin/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/wangbowen-hexo-blog/about" target="_blank">W.BOWEN</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/wangbowen-hexo-blog/tags/JavaScript/">
                                    <span class="chip bg-color">JavaScript</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/wangbowen-hexo-blog/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/wangbowen-hexo-blog/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        <img src="/wangbowen-hexo-blog/medias/reward/alipay.jpg" class="reward-img" alt="支付宝打赏二维码">
                    </div>
                    <div id="wechat">
                        <img src="/wangbowen-hexo-blog/medias/reward/wechat.png" class="reward-img" alt="微信打赏二维码">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    
        <style>
    .valine-card {
        margin: 1.5rem auto;
    }

    .valine-card .card-content {
        padding: 20px 20px 5px 20px;
    }

    #vcomments textarea {
        box-sizing: border-box;
        background: url("/wangbowen-hexo-blog/medias/comment_bg.png") 100% 100% no-repeat;
    }

    #vcomments p {
        margin: 2px 2px 10px;
        font-size: 1.05rem;
        line-height: 1.78rem;
    }

    #vcomments blockquote p {
        text-indent: 0.2rem;
    }

    #vcomments a {
        padding: 0 2px;
        color: #4cbf30;
        font-weight: 500;
        text-decoration: none;
    }

    #vcomments img {
        max-width: 100%;
        height: auto;
        cursor: pointer;
    }

    #vcomments ol li {
        list-style-type: decimal;
    }

    #vcomments ol,
    ul {
        display: block;
        padding-left: 2em;
        word-spacing: 0.05rem;
    }

    #vcomments ul li,
    ol li {
        display: list-item;
        line-height: 1.8rem;
        font-size: 1rem;
    }

    #vcomments ul li {
        list-style-type: disc;
    }

    #vcomments ul ul li {
        list-style-type: circle;
    }

    #vcomments table, th, td {
        padding: 12px 13px;
        border: 1px solid #dfe2e5;
    }

    #vcomments table, th, td {
        border: 0;
    }

    table tr:nth-child(2n), thead {
        background-color: #fafafa;
    }

    #vcomments table th {
        background-color: #f2f2f2;
        min-width: 80px;
    }

    #vcomments table td {
        min-width: 80px;
    }

    #vcomments h1 {
        font-size: 1.85rem;
        font-weight: bold;
        line-height: 2.2rem;
    }

    #vcomments h2 {
        font-size: 1.65rem;
        font-weight: bold;
        line-height: 1.9rem;
    }

    #vcomments h3 {
        font-size: 1.45rem;
        font-weight: bold;
        line-height: 1.7rem;
    }

    #vcomments h4 {
        font-size: 1.25rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    #vcomments h5 {
        font-size: 1.1rem;
        font-weight: bold;
        line-height: 1.4rem;
    }

    #vcomments h6 {
        font-size: 1rem;
        line-height: 1.3rem;
    }

    #vcomments p {
        font-size: 1rem;
        line-height: 1.5rem;
    }

    #vcomments hr {
        margin: 12px 0;
        border: 0;
        border-top: 1px solid #ccc;
    }

    #vcomments blockquote {
        margin: 15px 0;
        border-left: 5px solid #42b983;
        padding: 1rem 0.8rem 0.3rem 0.8rem;
        color: #666;
        background-color: rgba(66, 185, 131, .1);
    }

    #vcomments pre {
        font-family: monospace, monospace;
        padding: 1.2em;
        margin: .5em 0;
        background: #272822;
        overflow: auto;
        border-radius: 0.3em;
        tab-size: 4;
    }

    #vcomments code {
        font-family: monospace, monospace;
        padding: 1px 3px;
        font-size: 0.92rem;
        color: #e96900;
        background-color: #f8f8f8;
        border-radius: 2px;
    }

    #vcomments pre code {
        font-family: monospace, monospace;
        padding: 0;
        color: #e8eaf6;
        background-color: #272822;
    }

    #vcomments pre[class*="language-"] {
        padding: 1.2em;
        margin: .5em 0;
    }

    #vcomments code[class*="language-"],
    pre[class*="language-"] {
        color: #e8eaf6;
    }

    #vcomments [type="checkbox"]:not(:checked), [type="checkbox"]:checked {
        position: inherit;
        margin-left: -1.3rem;
        margin-right: 0.4rem;
        margin-top: -1px;
        vertical-align: middle;
        left: unset;
        visibility: visible;
    }

    #vcomments b,
    strong {
        font-weight: bold;
    }

    #vcomments dfn {
        font-style: italic;
    }

    #vcomments small {
        font-size: 85%;
    }

    #vcomments cite {
        font-style: normal;
    }

    #vcomments mark {
        background-color: #fcf8e3;
        padding: .2em;
    }

    #vcomments table, th, td {
        padding: 12px 13px;
        border: 1px solid #dfe2e5;
    }

    table tr:nth-child(2n), thead {
        background-color: #fafafa;
    }

    #vcomments table th {
        background-color: #f2f2f2;
        min-width: 80px;
    }

    #vcomments table td {
        min-width: 80px;
    }

    #vcomments [type="checkbox"]:not(:checked), [type="checkbox"]:checked {
        position: inherit;
        margin-left: -1.3rem;
        margin-right: 0.4rem;
        margin-top: -1px;
        vertical-align: middle;
        left: unset;
        visibility: visible;
    }
</style>

<div class="card valine-card" data-aos="fade-up">
    <div class="comment_headling" style="font-size: 20px; font-weight: 700; position: relative; padding-left: 20px; top: 15px; padding-bottom: 5px;">
        <i class="fas fa-comments fa-fw" aria-hidden="true"></i>
        <span>评论</span>
    </div>
    <div id="vcomments" class="card-content" style="display: grid">
    </div>
</div>

<script src="/wangbowen-hexo-blog/libs/valine/av-min.js"></script>
<script src="/wangbowen-hexo-blog/libs/valine/Valine.min.js"></script>
<script>
    new Valine({
        el: '#vcomments',
        appId: 'EDT5zRbrzUXInYp7SCupHY7m-gzGzoHsz',
        appKey: 'u9CyC9PTy66xmdnLhq7Hu8PX',
        notify: 'true' === 'true',
        verify: 'true' === 'true',
        visitor: 'true' === 'true',
        avatar: 'mm',
        pageSize: '10',
        lang: 'zh-cn',
        placeholder: '有好的建议请留言八！'
    });
</script>

<!--酷Q推送-->


    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/wangbowen-hexo-blog/2022/03/06/yi-xie-jie-jue-ban-fa/">
                    <div class="card-image">
                        
                        
                        <img src="/wangbowen-hexo-blog/medias/featureimages/22.jpg" class="responsive-img" alt="一些解决办法">
                        
                        <span class="card-title">一些解决办法</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2022-03-06
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-user fa-fw"></i>
                            W.BOWEN
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/wangbowen-hexo-blog/tags/Vue/">
                        <span class="chip bg-color">Vue</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/wangbowen-hexo-blog/2021/05/19/vue-xiang-guan-zhi-shi-dian/">
                    <div class="card-image">
                        
                        
                        <img src="/wangbowen-hexo-blog/medias/featureimages/15.jpg" class="responsive-img" alt="Vue相关知识点">
                        
                        <span class="card-title">Vue相关知识点</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2021-05-19
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-user fa-fw"></i>
                            W.BOWEN
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/wangbowen-hexo-blog/tags/Vue/">
                        <span class="chip bg-color">Vue</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>



<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/wangbowen-hexo-blog/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/wangbowen-hexo-blog/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/wangbowen-hexo-blog/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/wangbowen-hexo-blog/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/wangbowen-hexo-blog/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h2, h3, h4'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h2, h3, h4').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    
        <link rel="stylesheet" href="/wangbowen-hexo-blog/libs/aplayer/APlayer.min.css">
<style>
    .aplayer .aplayer-lrc p {
        
        display: none;
        
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        
        display: none;
        
        font-size: 15px;
        color: #42b983;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    
</style>
<div class="">
    
    <div class="row">
        <meting-js class="col l8 offset-l2 m10 offset-m1 s12"
                   server="netease"
                   type="playlist"
                   id="503838841"
                   fixed='true'
                   autoplay='true'
                   theme='#42b983'
                   loop='all'
                   order='random'
                   preload='auto'
                   volume='0.7'
                   list-folded='true'
        >
        </meting-js>
    </div>
</div>

<script src="/wangbowen-hexo-blog/libs/aplayer/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>

    
    <div class="container row center-align" style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2019-2024</span>
            
            <span id="year">2019</span>
            <a href="/wangbowen-hexo-blog/about" target="_blank">W.BOWEN</a>
            |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>
            
            
            
            
            
            
            <span id="busuanzi_container_site_pv">
                |&nbsp;<i class="far fa-eye"></i>&nbsp;总访问量:&nbsp;<span id="busuanzi_value_site_pv"
                    class="white-color"></span>&nbsp;次
            </span>
            
            
            <span id="busuanzi_container_site_uv">
                |&nbsp;<i class="fas fa-users"></i>&nbsp;总访问人数:&nbsp;<span id="busuanzi_value_site_uv"
                    class="white-color"></span>&nbsp;人
            </span>
            
            <br>
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link social-statis">
    <a href="https://gitee.com/wang-bowen" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>



    <a href="mailto:784801819@qq.com" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50">
        <i class="fas fa-envelope-open"></i>
    </a>







    <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=784801819" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 784801819" data-position="top" data-delay="50">
        <i class="fab fa-qq"></i>
    </a>







    <a href="/wangbowen-hexo-blog/atom.xml" class="tooltipped" target="_blank" data-tooltip="RSS 订阅" data-position="top" data-delay="50">
        <i class="fas fa-rss"></i>
    </a>

</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/wangbowen-hexo-blog/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/wangbowen-hexo-blog/libs/materialize/materialize.min.js"></script>
    <script src="/wangbowen-hexo-blog/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/wangbowen-hexo-blog/libs/aos/aos.js"></script>
    <script src="/wangbowen-hexo-blog/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/wangbowen-hexo-blog/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/wangbowen-hexo-blog/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/wangbowen-hexo-blog/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/wangbowen-hexo-blog/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

    <!--腾讯兔小巢-->
    
    

    

    

    
    <script src="/wangbowen-hexo-blog/libs/instantpage/instantpage.js" type="module"></script>
    

<script src="/wangbowen-hexo-blog/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"live2d-widget-model-z16"},"display":{"position":"right","width":200,"height":400},"mobile":{"show":false},"log":false});</script></body>

</html>
